diff --git a/arch/certificate_class/MC.yaml b/arch/certificate_class/MC.yaml index 923426680..cf2d7512c 100644 --- a/arch/certificate_class/MC.yaml +++ b/arch/certificate_class/MC.yaml @@ -1,35 +1,38 @@ -MC: - name: MC - long_name: Microcontroller Certificate Class +# yaml-language-server: $schema=../../schemas/cert_class_schema.json - introduction: | - This certification class specifies requirements for microcontrollers. - It targets microcontrollers running low-level software on an RTOS or bare-metal. - This CRD is not intended for the smallest possible microcontrollers but rather for applications - benefiting from a standardized microcontroller. - See the https://docs.google.com/document/d/133SZKc18tLsQcT1o6gEmBUkjwrtg2ow63me54RQ1jiY[RISC-V CRDs] - document for information relevant to all RISC-V CRDs. +$schema: cert_class_schema.json# +kind: certificate class +name: MC +long_name: Microcontroller Certificate Class - naming_scheme: | - The MC (M = Microcontroller, C = Certificate) has the following naming scheme (suffixes after MC - are optional but in the below order): +introduction: | + This certification class specifies requirements for microcontrollers. + It targets microcontrollers running low-level software on an RTOS or bare-metal. + This CRD is not intended for the smallest possible microcontrollers but rather for applications + benefiting from a standardized microcontroller. + See the https://docs.google.com/document/d/133SZKc18tLsQcT1o6gEmBUkjwrtg2ow63me54RQ1jiY[RISC-V CRDs] + document for information relevant to all RISC-V CRDs. - MC[v] +naming_scheme: | + The MC (M = Microcontroller, C = Certificate) has the following naming scheme (suffixes after MC + are optional but in the below order): - Where: + MC[v] - * Left & right square braces denote optional. - * \ is a 3 digit integer. It is changed only when mandatory extensions are added to a CRD. - ** The one's digit is incremented when a small mandatory extension is added (e.g., Zicond) - ** The ten's digit is incremented when a medium mandatory extension is addded (e.g., PMP) - ** The hundreds's digit is incremented when a large mandatory extension is addded (e.g., V or H) - * \ is a semantic version (see semver.org) formatted as [..[patch]]. If \ is omitted, the reference applies equally to all versions. - ** A release indicates support for a new optional extension. - ** A release indicates one or more of the following changes to the certification tests associated with the CRD. - *** Fix test bug or increase test coverage - *** Add more allowed parameter values - *** Support new extension version - ** A release indicates just CRD specification changes without any difference in functional behavior + Where: - mandatory_priv_modes: - - M \ No newline at end of file + * Left & right square braces denote optional. + * \ is a 3 digit integer. It is changed only when mandatory extensions are added to a CRD. + ** The one's digit is incremented when a small mandatory extension is added (e.g., Zicond) + ** The ten's digit is incremented when a medium mandatory extension is addded (e.g., PMP) + ** The hundreds's digit is incremented when a large mandatory extension is addded (e.g., V or H) + * \ is a semantic version (see semver.org) formatted as [..[patch]]. If \ is omitted, the reference applies equally to all versions. + ** A release indicates support for a new optional extension. + ** A release indicates one or more of the following changes to the certification tests associated with the CRD. + *** Fix test bug or increase test coverage + *** Add more allowed parameter values + *** Support new extension version + ** A release indicates just CRD specification changes without any difference in functional behavior + +mandatory_priv_modes: +- M \ No newline at end of file diff --git a/arch/certificate_class/MockCertificateClass.yaml b/arch/certificate_class/MockCertificateClass.yaml index 1cd6dbc0e..eebbbbbac 100644 --- a/arch/certificate_class/MockCertificateClass.yaml +++ b/arch/certificate_class/MockCertificateClass.yaml @@ -1,14 +1,16 @@ -MockCertificateClass: - name: MockCertificateClass - long_name: Mock Certificate Class Long Name +# yaml-language-server: $schema=../../schemas/cert_class_schema.json - introduction: | - Here's the Mock Certificate Class introduction. +$schema: cert_class_schema.json# +kind: certificate class +name: MockCertificateClass +long_name: Mock Certificate Class Long Name - naming_scheme: | - Here's the Mock Certificate Class naming scheme. +introduction: | + Here's the Mock Certificate Class introduction. - mandatory_priv_modes: - - M +naming_scheme: | + Here's the Mock Certificate Class naming scheme. + A Mock certificate class or model can have any name as long as it can be a hash key. - description: Here's the Mock Certificate Class description. \ No newline at end of file +mandatory_priv_modes: +- M diff --git a/arch/certificate_model/MC100.yaml b/arch/certificate_model/MC100.yaml index 48a4ecf40..a182de120 100644 --- a/arch/certificate_model/MC100.yaml +++ b/arch/certificate_model/MC100.yaml @@ -1,141 +1,142 @@ -# yaml-language-server: $schema=../../schemas/testplan_schema.json +# yaml-language-server: $schema=../../schemas/cert_model_schema.json -MC100: - name: MC100 - long_name: Basic Microcontroller Certificate - class: MC - model: 100 +$schema: cert_model_schema.json# +kind: certificate model +name: MC100 +long_name: Basic Microcontroller Certificate +class: + $ref: certificate_class/MC.yaml# - # Semantic versions within the model - versions: - - version: "1.0.0" +# Semantic versions within the model +versions: +- version: "1.0.0" - # XLEN used by rakefile - base: 32 +# XLEN used by rakefile +base: 32 - revision_history: - - revision: "0.7" - date: 2024-07-29 - changes: - - First version after moving non-microcontroller content in this document to a new document - called “RISC-V CRDs (Certification Requirement Documents)” - - Change MC100 Unpriv ISA spec from - “https://riscv.org/wp-content/uploads/2016/06/riscv-spec-v2.1.pdf[riscv-spec-v2.1], May 31, - 2016” to https://github.com/riscv/riscv-isa-manual/releases/tag/Ratified-IMAFDQC since the - former isn't ratified by the latter is the oldest ratified version. - - Added requirements for WFI instruction - - Added requirements related to msip memory-mapped register - - revision: "0.6" - date: 2024-07-11 - changes: - - Supporting multiple MC versions to support customers wanting to certify existing microcontrollers not using the latest version of ratified standards. - - Changed versioning scheme to use major.minor.patch instead of 3-digit major & minor. - - Added a table showing the mapping from MC version to ISA manuals. - - Reluctantly made interrupts OUT OF SCOPE for MC100 since only the CLINT interrupt controller - was ratified at that time and isn’t anticipated to be the interrupt controller used by MC100 implementations. - - Clarified MANDATORY behaviors for mie and mip CSRs - - Removed canonical discovery recipe because the OPT-* options directly inform the certification - tests and certification reference model of the status of the various options. Also, canonical - discovery recipes (e.g., probing for CLIC) violate the certification approach of avoiding writing - potentially illegal values to CSR fields. - - Added more options for interrupts - - Moved non-microcontroller content in this document to a new document called “RISC-V Certification Plans” - - revision: "0.5" - date: 2024-06-03 - changes: - - Renamed to “RISC-V Microcontroller Certification Plan” based on Jason’s recommendation - - Added mvendorid, marchid, mimpid, and mhardid read-only priv CSRs because Allen pointed out - these are mandatory in M-mode v1.13 (probably older versions too, haven’t looked yet). - - Added table showing mapping of MC versions to associated RISC-V specifications - - revision: "0.4" - date: 2024-06-03 - changes: - - Added M-mode instruction requirements - - Made Zicntr MANDATORY due to very low cost for implementations to support (in the spirit of minimizing options). - - Removed OPT-CNTR-PREC since minstret and mcycle must be a full 64 bits to be standard-compliant. - - revision: "0.3" - date: 2024-05-25 - changes: - - Includes Zicntr as OPTIONAL and then has only 32-bit counters for instret and cycle. - - revision: "0.2" - date: 2024-05-20 - changes: - - Very early draft - - revision: "0.1" - date: 2024-05-16 - changes: - - Initial version +revision_history: +- revision: "0.7.0" + date: 2024-07-29 + changes: + - First version after moving non-microcontroller content in this document to a new document + called "RISC-V CRDs (Certification Requirement Documents)" + - Change MC100 Unpriv ISA spec from + "https://riscv.org/wp-content/uploads/2016/06/riscv-spec-v2.1.pdf[riscv-spec-v2.1], May 31, + 2016" to https://github.com/riscv/riscv-isa-manual/releases/tag/Ratified-IMAFDQC since the + former isn't ratified by the latter is the oldest ratified version. + - Added requirements for WFI instruction + - Added requirements related to msip memory-mapped register +- revision: "0.6.0" + date: 2024-07-11 + changes: + - Supporting multiple MC versions to support customers wanting to certify existing microcontrollers not using the latest version of ratified standards. + - Changed versioning scheme to use major.minor.patch instead of 3-digit major & minor. + - Added a table showing the mapping from MC version to ISA manuals. + - Reluctantly made interrupts OUT OF SCOPE for MC100 since only the CLINT interrupt controller + was ratified at that time and isn't anticipated to be the interrupt controller used by MC100 implementations. + - Clarified MANDATORY behaviors for mie and mip CSRs + - Removed canonical discovery recipe because the OPT-* options directly inform the certification + tests and certification reference model of the status of the various options. Also, canonical + discovery recipes (e.g., probing for CLIC) violate the certification approach of avoiding writing + potentially illegal values to CSR fields. + - Added more options for interrupts + - Moved non-microcontroller content in this document to a new document called "RISC-V Certification Plans" +- revision: "0.5.0" + date: 2024-06-03 + changes: + - Renamed to "RISC-V Microcontroller Certification Plan" based on Jason's recommendation + - Added mvendorid, marchid, mimpid, and mhardid read-only priv CSRs because Allen pointed out + these are mandatory in M-mode v1.13 (probably older versions too, haven't looked yet). + - Added table showing mapping of MC versions to associated RISC-V specifications +- revision: "0.4.0" + date: 2024-06-03 + changes: + - Added M-mode instruction requirements + - Made Zicntr MANDATORY due to very low cost for implementations to support (in the spirit of minimizing options). + - Removed OPT-CNTR-PREC since minstret and mcycle must be a full 64 bits to be standard-compliant. +- revision: "0.3.0" + date: 2024-05-25 + changes: + - Includes Zicntr as OPTIONAL and then has only 32-bit counters for instret and cycle. +- revision: "0.2.0" + date: 2024-05-20 + changes: + - Very early draft +- revision: "0.1.0" + date: 2024-05-16 + changes: + - Initial version - description: | - MC100 can be though of as minimal 32-bit RISC-V processors with M-mode support: +description: | + MC100 can be though of as minimal 32-bit RISC-V processors with M-mode support: - * The Unprivileged ISA is RV32I with a few extensions suitable for a basic microcontroller - * The M-mode features are those listed as mandatory in the associated RISC-V Privileged ISA manual + * The Unprivileged ISA is RV32I with a few extensions suitable for a basic microcontroller + * The M-mode features are those listed as mandatory in the associated RISC-V Privileged ISA manual - Key features not included in MC100 (i.e., OUT OF SCOPE): + Key features not included in MC100 (i.e., OUT OF SCOPE): - * Interrupt Controller (e.g., CLIC, CLINT, PLIC) - * Features for modes other than M-mode - * PMP - * Debug & trace (TBD) + * Interrupt Controller (e.g., CLIC, CLINT, PLIC) + * Features for modes other than M-mode + * PMP + * Debug & trace (TBD) - # Specification versions - tsc_profile: null # None for MC100 - unpriv_isa_manual_revision: "20191213" - priv_isa_manual_revision: "20190608-Priv-MSU-Ratified" - debug_manual_revision: "0.13.2" +# Specification versions +tsc_profile: null # None for MC100 +unpriv_isa_manual_revision: "20191213" +priv_isa_manual_revision: "20190608-Priv-MSU-Ratified" +debug_manual_revision: "0.13.2" # XXX - Remove version information since specifying priv/unpriv ISA manual should imply this. - extensions: - I: - version: "~> 2.1" - presence: mandatory - C: - version: "~> 2.2" - presence: mandatory - M: - version: "~> 2.0" - presence: mandatory - Zicsr: - version: "~> 2.0" - presence: mandatory - Zicntr: - version: "~> 2.0" - presence: mandatory - parameters: - TIME_CSR_IMPLEMENTED: {} # Unconstrained - Sm: - version: "~> 1.11.0" - presence: mandatory - parameters: - MTVEC_BASE_ALIGNMENT_DIRECT: {} # Unconstrained - MTVEC_BASE_ALIGNMENT_VECTORED: {} # Unconstrained - ARCH_ID: {} # Unconstrained - IMP_ID: {} # Unconstrained - VENDOR_ID_BANK: {} # Unconstrained - VENDOR_ID_OFFSET: {} # Unconstrained - MISA_CSR_IMPLEMENTED: {} # Unconstrained - MTVAL_WIDTH: {} # Unconstrained - MTVEC_MODES: {} # Unconstrained - PHYS_ADDR_WIDTH: {} # Unconstrained - MISALIGNED_LDST: {} # Unconstrained - MISALIGNED_LDST_EXCEPTION_PRIORITY : {} # Unconstrained - MISALIGNED_MAX_ATOMICITY_GRANULE_SIZE: {} # Unconstrained - MISALIGNED_SPLIT_STRATEGY: - schema: - const: by_byte - PRECISE_SYNCHRONOUS_EXCEPTIONS: - schema: - const: true - TRAP_ON_ECALL_FROM_M: - schema: - const: true - TRAP_ON_EBREAK: - schema: - const: true - M_MODE_ENDIANESS: - schema: - const: little - XLEN: - schema: - const: 32 \ No newline at end of file +extensions: + I: + version: "~> 2.1" + presence: mandatory + C: + version: "~> 2.2" + presence: mandatory + M: + version: "~> 2.0" + presence: mandatory + Zicsr: + version: "~> 2.0" + presence: mandatory + Zicntr: + version: "~> 2.0" + presence: mandatory + parameters: + TIME_CSR_IMPLEMENTED: {} # Unconstrained + Sm: + version: "~> 1.11.0" + presence: mandatory + parameters: + MTVEC_BASE_ALIGNMENT_DIRECT: {} # Unconstrained + MTVEC_BASE_ALIGNMENT_VECTORED: {} # Unconstrained + ARCH_ID: {} # Unconstrained + IMP_ID: {} # Unconstrained + VENDOR_ID_BANK: {} # Unconstrained + VENDOR_ID_OFFSET: {} # Unconstrained + MISA_CSR_IMPLEMENTED: {} # Unconstrained + MTVAL_WIDTH: {} # Unconstrained + MTVEC_MODES: {} # Unconstrained + PHYS_ADDR_WIDTH: {} # Unconstrained + MISALIGNED_LDST: {} # Unconstrained + MISALIGNED_LDST_EXCEPTION_PRIORITY : {} # Unconstrained + MISALIGNED_MAX_ATOMICITY_GRANULE_SIZE: {} # Unconstrained + MISALIGNED_SPLIT_STRATEGY: + schema: + const: by_byte + PRECISE_SYNCHRONOUS_EXCEPTIONS: + schema: + const: true + TRAP_ON_ECALL_FROM_M: + schema: + const: true + TRAP_ON_EBREAK: + schema: + const: true + M_MODE_ENDIANESS: + schema: + const: little + XLEN: + schema: + const: 32 \ No newline at end of file diff --git a/arch/certificate_model/MockCertificateModel.yaml b/arch/certificate_model/MockCertificateModel.yaml index 0d09bb950..2f19b00b5 100644 --- a/arch/certificate_model/MockCertificateModel.yaml +++ b/arch/certificate_model/MockCertificateModel.yaml @@ -1,225 +1,226 @@ -# yaml-language-server: $schema=../../schemas/testplan_schema.json +# yaml-language-server: $schema=../../schemas/cert_model_schema.json -MockCertificateModel: - name: MockCertificateModel - long_name: Mock Certificate Model Long Name - class: MockCertificateClass - model: MockModel - - # XLEN used by rakefile - base: 64 +$schema: cert_model_schema.json# +kind: certificate model +name: MockCertificateModel +long_name: Mock Certificate Model Long Name +class: + $ref: certificate_class/MockCertificateClass.yaml# - # Semantic versions within the model - versions: - - version: "1.0.0" - - version: "1.1.0" + # XLEN used by rakefile +base: 64 - revision_history: - - revision: "0.1" - date: 2024-10-04 - changes: - - Created to test CRDs - - revision: "0.2" - date: 2024-10-05 - changes: - - Also created to test CRDs +# Semantic versions within the model +versions: + - version: "1.0.0" + - version: "1.1.0" - description: | - Mock CRD description: +revision_history: +- revision: "0.1.0" + date: 2024-10-04 + changes: + - Created to test CRDs +- revision: "0.2.0" + date: 2024-10-05 + changes: + - Also created to test CRDs - * Hello - * Bob! +description: | + Mock CRD description: - # Specification versions - tsc_profile: null - unpriv_isa_manual_revision: "20191213" - priv_isa_manual_revision: "20190608-Priv-MSU-Ratified" - debug_manual_revision: "0.13.2" + * Hello + * Bob! + +# Specification versions +tsc_profile: null +unpriv_isa_manual_revision: "20191213" +priv_isa_manual_revision: "20190608-Priv-MSU-Ratified" +debug_manual_revision: "0.13.2" # XXX - Remove version information since specifying priv/unpriv ISA manual should imply this. - extensions: - $inherits: - - "../profile_release/MockProfileRelease.yaml#/MockProfileRelease/profiles/MP-U-64/extensions" - - "../profile_release/MockProfileRelease.yaml#/MockProfileRelease/profiles/MP-S-64/extensions" - I: - note: Just added this note to I extension - MockExt: - presence: mandatory - parameters: - MOCK_ENUM_2_INTS: {} - MOCK_ENUM_2_STRINGS: {} - MOCK_BOOL_1: {} - MOCK_BOOL_2: +extensions: + $inherits: + - "profile_release/MockProfileRelease.yaml#/MockProfileRelease/profiles/MP-U-64/extensions" + - "profile_release/MockProfileRelease.yaml#/MockProfileRelease/profiles/MP-S-64/extensions" + I: + note: Just added this note to I extension + MockExt: + presence: mandatory + parameters: + MOCK_ENUM_2_INTS: {} + MOCK_ENUM_2_STRINGS: {} + MOCK_BOOL_1: {} + MOCK_BOOL_2: + schema: + const: true + MOCK_1_BIT_INT: {} + MOCK_2_BIT_INT: {} + MOCK_25_BIT_INT: {} + MOCK_32_BIT_INT: + schema: + const: 0xdeadbeef + MOCK_64_BIT_INT: {} + MOCK_INT_RANGE_0_TO_127: {} + MOCK_INT_RANGE_0_TO_128: {} + MOCK_INT_RANGE_1_TO_128: {} + MOCK_INT_RANGE_0_TO_999: {} + MOCK_INT_RANGE_0_TO_1023: {} + MOCK_INT_RANGE_1000_TO_2048: {} + MOCK_ARRAY_INT_ENUM: {} + MOCK_ARRAY_BOOL_ARRAY_OF_8_FIRST_2_FALSE: {} + MOCK_ARRAY_STRING_ENUM1: + schema: + const : DEF + MOCK_ARRAY_STRING_ENUM2: + schema: + contains: { const : DEF } + C: + version: "~> 2.2" + presence: mandatory + parameters: + MUTABLE_MISA_C: + schema: + const: false + note: | + Here's a multi-line note + + for the C extension. + Zicsr: + version: "~> 2.0" + presence: mandatory + Zicntr: + version: "~> 2.0" + presence: mandatory + parameters: + TIME_CSR_IMPLEMENTED: {} # Unconstrained + Sm: + version: "~> 1.11" + presence: mandatory + parameters: + MTVEC_BASE_ALIGNMENT_DIRECT: {} # Unconstrained + MTVEC_BASE_ALIGNMENT_VECTORED: {} # Unconstrained + ARCH_ID: {} # Unconstrained + IMP_ID: {} # Unconstrained + VENDOR_ID_BANK: {} # Unconstrained + VENDOR_ID_OFFSET: {} # Unconstrained + MISA_CSR_IMPLEMENTED: {} # Unconstrained + MTVAL_WIDTH: {} # Unconstrained + MTVEC_MODES: + note: Here's a note for MTVEC_MODES parameter. + schema: + contains: { const : 0 } + PHYS_ADDR_WIDTH: {} # Unconstrained + PRECISE_SYNCHRONOUS_EXCEPTIONS: + schema: + const: true + TRAP_ON_ECALL_FROM_M: + schema: + const: true + TRAP_ON_EBREAK: + schema: + const: true + REPORT_VA_IN_MTVAL_ON_BREAKPOINT: + schema: + const: true + REPORT_VA_IN_MTVAL_ON_INSTRUCTION_ACCESS_FAULT: + schema: + const: true + REPORT_VA_IN_MTVAL_ON_LOAD_ACCESS_FAULT: + schema: + const: true + REPORT_VA_IN_MTVAL_ON_STORE_AMO_ACCESS_FAULT: schema: const: true - MOCK_1_BIT_INT: {} - MOCK_2_BIT_INT: {} - MOCK_25_BIT_INT: {} - MOCK_32_BIT_INT: + REPORT_ENCODING_IN_MTVAL_ON_ILLEGAL_INSTRUCTION: + schema: + const: true + M_MODE_ENDIANESS: + schema: + const: little + # Uncomment when GitHub issue # is fixed. + #schema: + #- when: + # version: "=1.0.0" + # then: + # const: little + #- when: + # version: "=1.1.0" + # then: + # enum: [little, big] + XLEN: + schema: + const: 64 + CONFIG_PTR_ADDRESS: schema: const: 0xdeadbeef - MOCK_64_BIT_INT: {} - MOCK_INT_RANGE_0_TO_127: {} - MOCK_INT_RANGE_0_TO_128: {} - MOCK_INT_RANGE_1_TO_128: {} - MOCK_INT_RANGE_0_TO_999: {} - MOCK_INT_RANGE_0_TO_1023: {} - MOCK_INT_RANGE_1000_TO_2048: {} - MOCK_ARRAY_INT_ENUM: {} - MOCK_ARRAY_BOOL_ARRAY_OF_8_FIRST_2_FALSE: {} - MOCK_ARRAY_STRING_ENUM1: + note: "This parameter and its associated CSR shouldn't be here. See GitHub issue #53." + Zifencei: + presence: optional + note: "Here's a note for Zifencei" + Zicbop: + presence: optional + note: "Testing CACHE_BLOCK_SIZE parameter which is also defined by Zicbom." + parameters: + CACHE_BLOCK_SIZE: schema: - const : DEF - MOCK_ARRAY_STRING_ENUM2: + const: 64 + Zicbom: + presence: optional + note: "Testing CACHE_BLOCK_SIZE parameter which is also defined by Zicbop." + parameters: + CACHE_BLOCK_SIZE: schema: - contains: { const : DEF } - C: - version: "~> 2.2" - presence: mandatory - parameters: - MUTABLE_MISA_C: - schema: - const: false - note: | - Here's a multi-line note + - for the C extension. - Zicsr: - version: "~> 2.0" - presence: mandatory - Zicntr: - version: "~> 2.0" - presence: mandatory - parameters: - TIME_CSR_IMPLEMENTED: {} # Unconstrained - Sm: - version: "~> 1.11" - presence: mandatory - parameters: - MTVEC_BASE_ALIGNMENT_DIRECT: {} # Unconstrained - MTVEC_BASE_ALIGNMENT_VECTORED: {} # Unconstrained - ARCH_ID: {} # Unconstrained - IMP_ID: {} # Unconstrained - VENDOR_ID_BANK: {} # Unconstrained - VENDOR_ID_OFFSET: {} # Unconstrained - MISA_CSR_IMPLEMENTED: {} # Unconstrained - MTVAL_WIDTH: {} # Unconstrained - MTVEC_MODES: - note: Here's a note for MTVEC_MODES parameter. - schema: - contains: { const : 0 } - PHYS_ADDR_WIDTH: {} # Unconstrained - PRECISE_SYNCHRONOUS_EXCEPTIONS: - schema: - const: true - TRAP_ON_ECALL_FROM_M: - schema: - const: true - TRAP_ON_EBREAK: - schema: - const: true - REPORT_VA_IN_MTVAL_ON_BREAKPOINT: - schema: - const: true - REPORT_VA_IN_MTVAL_ON_INSTRUCTION_ACCESS_FAULT: - schema: - const: true - REPORT_VA_IN_MTVAL_ON_LOAD_ACCESS_FAULT: - schema: - const: true - REPORT_VA_IN_MTVAL_ON_STORE_AMO_ACCESS_FAULT: - schema: - const: true - REPORT_ENCODING_IN_MTVAL_ON_ILLEGAL_INSTRUCTION: - schema: - const: true - M_MODE_ENDIANESS: - schema: - const: little - # Uncomment when GitHub issue # is fixed. - #schema: - #- when: - # version: "=1.0.0" - # then: - # const: little - #- when: - # version: "=1.1.0" - # then: - # enum: [little, big] - XLEN: - schema: - const: 64 - CONFIG_PTR_ADDRESS: - schema: - const: 0xdeadbeef - note: "This parameter and its associated CSR shouldn't be here. See GitHub issue #53." - Zifencei: - presence: optional - note: "Here's a note for Zifencei" - Zicbop: - presence: optional - note: "Testing CACHE_BLOCK_SIZE parameter which is also defined by Zicbom." - parameters: - CACHE_BLOCK_SIZE: - schema: - const: 64 - Zicbom: - presence: optional - note: "Testing CACHE_BLOCK_SIZE parameter which is also defined by Zicbop." - parameters: - CACHE_BLOCK_SIZE: - schema: - const: 64 - Zba: - presence: mandatory - version: "~> 1.0" - note: "Added these as mandatory to see if bug in profiles not listing instructions in appendix is here in CRD too." - Zbb: - presence: mandatory - version: "~> 1.0" - note: "Added these as mandatory to see if bug in profiles not listing instructions in appendix is here in CRD too." - Zbs: - presence: mandatory - version: "~> 1.0" - note: "Added these as mandatory to see if bug in profiles not listing instructions in appendix is here in CRD too." - - requirement_groups: - - name: Req-Grp-Any-XLEN - description: | - A bunch of additional requirements not associated with an extension. - requirements: - - name: REQ-ANY-XLEN-001 - description: Must pay your taxes on time - - name: REQ-ANY-XLEN-002 - description: Don't count your chickens before they're hatched! + const: 64 + Zba: + presence: mandatory + version: "~> 1.0" + note: "Added these as mandatory to see if bug in profiles not listing instructions in appendix is here in CRD too." + Zbb: + presence: mandatory + version: "~> 1.0" + note: "Added these as mandatory to see if bug in profiles not listing instructions in appendix is here in CRD too." + Zbs: + presence: mandatory + version: "~> 1.0" + note: "Added these as mandatory to see if bug in profiles not listing instructions in appendix is here in CRD too." + +requirement_groups: + - name: Req-Grp-Any-XLEN + description: | + A bunch of additional requirements not associated with an extension. + requirements: + - name: REQ-ANY-XLEN-001 + description: Must pay your taxes on time + - name: REQ-ANY-XLEN-002 + description: Don't count your chickens before they're hatched! - - name: Req-Grp-XLEN32 - when: - xlen: 32 - description: | - A bunch of additional requirements only that should show up for XLEN=32 - requirements: - - name: REQ-XLEN32-001 - description: Need lots of extra CSRs with `h` suffix + - name: Req-Grp-XLEN32 + when: + xlen: 32 + description: | + A bunch of additional requirements only that should show up for XLEN=32 + requirements: + - name: REQ-XLEN32-001 + description: Need lots of extra CSRs with `h` suffix - - name: Req-Grp-XLEN64 - when: - xlen: 64 - description: | - A bunch of additional requirements only that should show up for XLEN=64 - requirements: - - name: REQ-XLEN64-001 - description: Can avoid adding extra CSRs with `h` suffix - extra_notes: - - presence: optional - text: Here's the first extra note for the optional extensions section. - - presence: mandatory - text: | - Here's the first extra note for the mandatory extensions section. - This note is multiple lines. - - presence: optional - text: Here's the second extra note for the optional extensions section. - recommendations: - - text: | - Implementations are strongly recommended to raise illegal-instruction - exceptions on attempts to execute unimplemented opcodes. - - text: Micky should give Pluto an extra treat \ No newline at end of file + - name: Req-Grp-XLEN64 + when: + xlen: 64 + description: | + A bunch of additional requirements only that should show up for XLEN=64 + requirements: + - name: REQ-XLEN64-001 + description: Can avoid adding extra CSRs with `h` suffix +extra_notes: +- presence: optional + text: Here's the first extra note for the optional extensions section. +- presence: mandatory + text: | + Here's the first extra note for the mandatory extensions section. + This note is multiple lines. +- presence: optional + text: Here's the second extra note for the optional extensions section. +recommendations: +- text: | + Implementations are strongly recommended to raise illegal-instruction + exceptions on attempts to execute unimplemented opcodes. +- text: Micky should give Pluto an extra treat \ No newline at end of file diff --git a/arch/csr/F/fcsr.yaml b/arch/csr/F/fcsr.yaml index 72d797472..3948be255 100644 --- a/arch/csr/F/fcsr.yaml +++ b/arch/csr/F/fcsr.yaml @@ -1,182 +1,184 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -fcsr: - long_name: Floating-point control and status register (`frm` + `fflags`) - address: 0x003 - description: | - The floating-point control and status register, `fcsr`, is a RISC-V - control and status register (CSR). It is a 32-bit read/write register - that selects the dynamic rounding mode for floating-point arithmetic - operations and holds the accrued exception flags, as shown in <>. - - [[fcsr, Floating-Point Control and Status Register]] - .Floating-point control and status register - include::images/wavedrom/float-csr.adoc[] - - The `fcsr` register can be read and written with the FRCSR and FSCSR - instructions, which are assembler pseudoinstructions built on the - underlying CSR access instructions. FRCSR reads `fcsr` by copying it - into integer register _rd_. FSCSR swaps the value in `fcsr` by copying - the original value into integer register _rd_, and then writing a new - value obtained from integer register _rs1_ into `fcsr`. - - The fields within the `fcsr` can also be accessed individually through - different CSR addresses, and separate assembler pseudoinstructions are defined - for these accesses. The FRRM instruction reads the Rounding Mode field `frm` - (`fcsr` bits 7--5) and copies it into the least-significant three bits of - integer register _rd_, with zero in all other bits. FSRM swaps the value in - `frm` by copying the original value into integer register _rd_, and then - writing a new value obtained from the three least-significant bits of integer - register _rs1_ into `frm`. FRFLAGS and FSFLAGS are defined analogously for the - Accrued Exception Flags field `fflags` (`fcsr` bits 4--0). - - Bits 31--8 of the `fcsr` are reserved for other standard extensions. If - these extensions are not present, implementations shall ignore writes to - these bits and supply a zero value when read. Standard software should - preserve the contents of these bits. - - Floating-point operations use either a static rounding mode encoded in - the instruction, or a dynamic rounding mode held in `frm`. Rounding - modes are encoded as shown in <>. A value of 111 in the - instruction's _rm_ field selects the dynamic rounding mode held in - `frm`. The behavior of floating-point instructions that depend on - rounding mode when executed with a reserved rounding mode is _reserved_, including both static reserved rounding modes (101-110) and dynamic reserved rounding modes (101-111). Some instructions, including widening conversions, have the _rm_ field but are nevertheless mathematically unaffected by the rounding mode; software should set their _rm_ field to - RNE (000) but implementations must treat the _rm_ field as usual (in - particular, with regard to decoding legal vs. reserved encodings). - - [NOTE] - ==== - The C99 language standard effectively mandates the provision of a - dynamic rounding mode register. In typical implementations, writes to - the dynamic rounding mode CSR state will serialize the pipeline. Static - rounding modes are used to implement specialized arithmetic operations - that often have to switch frequently between different rounding modes. - - The ratified version of the F spec mandated that an illegal-instruction - exception was raised when an instruction was executed with a reserved - dynamic rounding mode. This has been weakened to reserved, which matches - the behavior of static rounding-mode instructions. Raising an - illegal-instruction exception is still valid behavior when encountering a - reserved encoding, so implementations compatible with the ratified spec - are compatible with the weakened spec. - ==== - - The accrued exception flags indicate the exception conditions that have - arisen on any floating-point arithmetic instruction since the field was - last reset by software, as shown in <>. The base - RISC-V ISA does not support generating a trap on the setting of a - floating-point exception flag. - (((floating-point, exception flag))) - - [[bitdef]] - .Accrued exception flag encoding. - [%autowidth,float="center",align="center",cols="^,<",options="header",] - |=== - |Flag Mnemonic |Flag Meaning - |NV |Invalid Operation - |DZ |Divide by Zero - |OF |Overflow - |UF |Underflow - |NX |Inexact - |=== - - [NOTE] - ==== - As allowed by the standard, we do not support traps on floating-point - exceptions in the F extension, but instead require explicit checks of - the flags in software. We considered adding branches controlled directly - by the contents of the floating-point accrued exception flags, but - ultimately chose to omit these instructions to keep the ISA simple. - ==== - - priv_mode: U - length: 32 - definedBy: F - fields: - FRM: - location: 7-5 - description: | - Rounding modes are encoded as follows: - - [[rm]] - .Rounding mode encoding. - [%autowidth,float="center",align="center",cols="^,^,<",options="header"] - !=== - !Rounding Mode |Mnemonic |Meaning - !000 !RNE !Round to Nearest, ties to Even - !001 !RTZ !Round towards Zero - !010 !RDN !Round Down (towards latexmath:[$-\infty$]) - !011 !RUP !Round Up (towards latexmath:[$+\infty$]) - !100 !RMM !Round to Nearest, ties to Max Magnitude - !101 ! !_Reserved for future use._ - !110 ! !_Reserved for future use._ - !111 !DYN !In instruction's _rm_ field, selects dynamic rounding mode; In Rounding Mode register, _reserved_. - !=== - - A value of 111 in the - instruction's _rm_ field selects the dynamic rounding mode held in - `frm`. The behavior of floating-point instructions that depend on - rounding mode when executed with a reserved rounding mode is _reserved_, - including both static reserved rounding modes (101-110) and dynamic reserved - rounding modes (101-111). Some instructions, including widening conversions, - have the _rm_ field but are nevertheless mathematically unaffected by the - rounding mode; software should set their _rm_ field to - RNE (000) but implementations must treat the _rm_ field as usual (in - particular, with regard to decoding legal vs. reserved encodings). - type: RW-H - reset_value: UNDEFINED_LEGAL - NV: - location: 4 - description: | - *Invalid Operation* - - Cumulative error flag for floating point operations. - - Set by hardware when a floating point operation is invalid and stays set until explicitly - cleared by software. - type: RW-H - reset_value: UNDEFINED_LEGAL - DZ: - location: 3 - description: | - *Divide by zero* - - Cumulative error flag for floating point operations. - - Set by hardware when a floating point divide attempts to divide by zero and stays set until explicitly - cleared by software. - type: RW-H - reset_value: UNDEFINED_LEGAL - OF: - location: 2 - description: | - *Overflow* - - Cumulative error flag for floating point operations. - - Set by hardware when a floating point operation overflows and stays set until explicitly - cleared by software. - type: RW-H - reset_value: UNDEFINED_LEGAL - UF: - location: 1 - description: | - *Underflow* - - Cumulative error flag for floating point operations. - - Set by hardware when a floating point operation underflows and stays set until explicitly - cleared by software. - type: RW-H - reset_value: UNDEFINED_LEGAL - NX: - location: 0 - description: | - *Inexact* - - Cumulative error flag for floating point operations. - - Set by hardware when a floating point operation is inexact and stays set until explicitly - cleared by software. - type: RW-H - reset_value: UNDEFINED_LEGAL \ No newline at end of file +$schema: "csr_schema.json#" +kind: csr +name: fcsr +long_name: Floating-point control and status register (`frm` + `fflags`) +address: 0x003 +description: | + The floating-point control and status register, `fcsr`, is a RISC-V + control and status register (CSR). It is a 32-bit read/write register + that selects the dynamic rounding mode for floating-point arithmetic + operations and holds the accrued exception flags, as shown in <>. + + [[fcsr, Floating-Point Control and Status Register]] + .Floating-point control and status register + include::images/wavedrom/float-csr.adoc[] + + The `fcsr` register can be read and written with the FRCSR and FSCSR + instructions, which are assembler pseudoinstructions built on the + underlying CSR access instructions. FRCSR reads `fcsr` by copying it + into integer register _rd_. FSCSR swaps the value in `fcsr` by copying + the original value into integer register _rd_, and then writing a new + value obtained from integer register _rs1_ into `fcsr`. + + The fields within the `fcsr` can also be accessed individually through + different CSR addresses, and separate assembler pseudoinstructions are defined + for these accesses. The FRRM instruction reads the Rounding Mode field `frm` + (`fcsr` bits 7--5) and copies it into the least-significant three bits of + integer register _rd_, with zero in all other bits. FSRM swaps the value in + `frm` by copying the original value into integer register _rd_, and then + writing a new value obtained from the three least-significant bits of integer + register _rs1_ into `frm`. FRFLAGS and FSFLAGS are defined analogously for the + Accrued Exception Flags field `fflags` (`fcsr` bits 4--0). + + Bits 31--8 of the `fcsr` are reserved for other standard extensions. If + these extensions are not present, implementations shall ignore writes to + these bits and supply a zero value when read. Standard software should + preserve the contents of these bits. + + Floating-point operations use either a static rounding mode encoded in + the instruction, or a dynamic rounding mode held in `frm`. Rounding + modes are encoded as shown in <>. A value of 111 in the + instruction's _rm_ field selects the dynamic rounding mode held in + `frm`. The behavior of floating-point instructions that depend on + rounding mode when executed with a reserved rounding mode is _reserved_, including both static reserved rounding modes (101-110) and dynamic reserved rounding modes (101-111). Some instructions, including widening conversions, have the _rm_ field but are nevertheless mathematically unaffected by the rounding mode; software should set their _rm_ field to + RNE (000) but implementations must treat the _rm_ field as usual (in + particular, with regard to decoding legal vs. reserved encodings). + + [NOTE] + ==== + The C99 language standard effectively mandates the provision of a + dynamic rounding mode register. In typical implementations, writes to + the dynamic rounding mode CSR state will serialize the pipeline. Static + rounding modes are used to implement specialized arithmetic operations + that often have to switch frequently between different rounding modes. + + The ratified version of the F spec mandated that an illegal-instruction + exception was raised when an instruction was executed with a reserved + dynamic rounding mode. This has been weakened to reserved, which matches + the behavior of static rounding-mode instructions. Raising an + illegal-instruction exception is still valid behavior when encountering a + reserved encoding, so implementations compatible with the ratified spec + are compatible with the weakened spec. + ==== + + The accrued exception flags indicate the exception conditions that have + arisen on any floating-point arithmetic instruction since the field was + last reset by software, as shown in <>. The base + RISC-V ISA does not support generating a trap on the setting of a + floating-point exception flag. + (((floating-point, exception flag))) + + [[bitdef]] + .Accrued exception flag encoding. + [%autowidth,float="center",align="center",cols="^,<",options="header",] + |=== + |Flag Mnemonic |Flag Meaning + |NV |Invalid Operation + |DZ |Divide by Zero + |OF |Overflow + |UF |Underflow + |NX |Inexact + |=== + + [NOTE] + ==== + As allowed by the standard, we do not support traps on floating-point + exceptions in the F extension, but instead require explicit checks of + the flags in software. We considered adding branches controlled directly + by the contents of the floating-point accrued exception flags, but + ultimately chose to omit these instructions to keep the ISA simple. + ==== + +priv_mode: U +length: 32 +definedBy: F +fields: + FRM: + location: 7-5 + description: | + Rounding modes are encoded as follows: + + [[rm]] + .Rounding mode encoding. + [%autowidth,float="center",align="center",cols="^,^,<",options="header"] + !=== + !Rounding Mode |Mnemonic |Meaning + !000 !RNE !Round to Nearest, ties to Even + !001 !RTZ !Round towards Zero + !010 !RDN !Round Down (towards latexmath:[$-\infty$]) + !011 !RUP !Round Up (towards latexmath:[$+\infty$]) + !100 !RMM !Round to Nearest, ties to Max Magnitude + !101 ! !_Reserved for future use._ + !110 ! !_Reserved for future use._ + !111 !DYN !In instruction's _rm_ field, selects dynamic rounding mode; In Rounding Mode register, _reserved_. + !=== + + A value of 111 in the + instruction's _rm_ field selects the dynamic rounding mode held in + `frm`. The behavior of floating-point instructions that depend on + rounding mode when executed with a reserved rounding mode is _reserved_, + including both static reserved rounding modes (101-110) and dynamic reserved + rounding modes (101-111). Some instructions, including widening conversions, + have the _rm_ field but are nevertheless mathematically unaffected by the + rounding mode; software should set their _rm_ field to + RNE (000) but implementations must treat the _rm_ field as usual (in + particular, with regard to decoding legal vs. reserved encodings). + type: RW-H + reset_value: UNDEFINED_LEGAL + NV: + location: 4 + description: | + *Invalid Operation* + + Cumulative error flag for floating point operations. + + Set by hardware when a floating point operation is invalid and stays set until explicitly + cleared by software. + type: RW-H + reset_value: UNDEFINED_LEGAL + DZ: + location: 3 + description: | + *Divide by zero* + + Cumulative error flag for floating point operations. + + Set by hardware when a floating point divide attempts to divide by zero and stays set until explicitly + cleared by software. + type: RW-H + reset_value: UNDEFINED_LEGAL + OF: + location: 2 + description: | + *Overflow* + + Cumulative error flag for floating point operations. + + Set by hardware when a floating point operation overflows and stays set until explicitly + cleared by software. + type: RW-H + reset_value: UNDEFINED_LEGAL + UF: + location: 1 + description: | + *Underflow* + + Cumulative error flag for floating point operations. + + Set by hardware when a floating point operation underflows and stays set until explicitly + cleared by software. + type: RW-H + reset_value: UNDEFINED_LEGAL + NX: + location: 0 + description: | + *Inexact* + + Cumulative error flag for floating point operations. + + Set by hardware when a floating point operation is inexact and stays set until explicitly + cleared by software. + type: RW-H + reset_value: UNDEFINED_LEGAL \ No newline at end of file diff --git a/arch/csr/H/hcounteren.layout b/arch/csr/H/hcounteren.layout index 9fb773cf7..d4b035ed1 100644 --- a/arch/csr/H/hcounteren.layout +++ b/arch/csr/H/hcounteren.layout @@ -1,166 +1,168 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -hcounteren: - long_name: Hypervisor Counter Enable - address: 0x606 - priv_mode: S - length: 32 - description: | - Together with `scounteren`, delegates control of the hardware performance-monitoring counters - to VS/VU-mode - - See `cycle` for a table describing how exceptions occur. - definedBy: H - fields: - CY: - location: 0 - description: | - When all of `scounteren.CY`, `mcounteren.CY`, and `hcounteren.CY` are set, - the `cycle` CSR (an alias of `mcycle`) is accessible to VU-mode. - - When `mcounteren.CY` and `hcounteren.CY` are set, - the `cycle` CSR (an alias of `mcycle`) is accessible to VS-mode. - - When `hcounteren.CY` is clear and `mcounteren.CY` is set, then any access to `cycle` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",cols="1,1,1,4,4"] - !=== - .2+h! [.rotate]#`hcounteren.CY`# .2+h! [.rotate]#`mcounteren.CY`# .2+h! [.rotate]#`scounteren.CY`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - definedBy: Zicntr - type(): | - if (HCOUNTENABLE_EN[0]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[0]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - TM: - location: 1 - description: | - When all of `scounteren.TM`, `mcounteren.TM`, and `hcounteren.TM` are set, - the `time` CSR (an alias of `mtime` memory-mapped CSR) is accessible to VU-mode. - - When `mcounteren.TM` and `hcounteren.TM` are set, - the `time` CSR (an alias of `mtime`) is accessible to VS-mode. - - When `hcounteren.TM` is clear and `mcounteren.TM` is set, then any access to `time` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.TM`# .2+h! [.rotate]#`mcounteren.TM`# .2+h! [.rotate]#`scounteren.TM`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - definedBy: Zicntr - type(): | - if (HCOUNTENABLE_EN[1]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[1]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - IR: - location: 2 - description: | - When all of `scounteren.IR`, `mcounteren.IR`, and `hcounteren.IR` are set, - the `instret` CSR (an alias of `minstret`) is accessible to VU-mode. - - When `mcounteren.IR` and `hcounteren.IR` are set, - the `instret` CSR (an alias of `minstret`) is accessible to VS-mode. - - When `hcounteren.IR` is clear and `mcounteren.IR` is set, then any access to `instret` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.IR`# .2+h! [.rotate]#`mcounteren.IR`# .2+h! [.rotate]#`scounteren.IR`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[2]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[2]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - <%- (3..31).each do |hpm_num| -%> - HPM<%= hpm_num %>: - location: <%= hpm_num %> - description: | - When all of `scounteren.HPM<%= hpm_num %>`, `mcounteren.HPM<%= hpm_num %>`, and `hcounteren.HPM<%= hpm_num %>` are set, - the `hpmcounter<%= hpm_num %>` CSR (an alias of `mhpmcounter<%= hpm_num %>`) is accessible to VU-mode. - - When `mcounteren.HPM<%= hpm_num %>` and `hcounteren.HPM<%= hpm_num %>` are set, - the `hpmcounter<%= hpm_num %>` CSR (an alias of `mhpmcounter<%= hpm_num %>`) is accessible to VS-mode. - - When `hcounteren.HPM<%= hpm_num %>` is clear and `mcounteren.HPM<%= hpm_num %>` is set, then any access to `hpmcounter<%= hpm_num %>` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`mcounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`scounteren.HPM<%= hpm_num %>`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[<%= hpm_num %>]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[<%= hpm_num %>]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - <%- end -%> +$schema: csr_schema.json# +kind: csr +name: hcounteren +long_name: Hypervisor Counter Enable +address: 0x606 +priv_mode: S +length: 32 +description: | + Together with `scounteren`, delegates control of the hardware performance-monitoring counters + to VS/VU-mode + + See `cycle` for a table describing how exceptions occur. +definedBy: H +fields: + CY: + location: 0 + description: | + When all of `scounteren.CY`, `mcounteren.CY`, and `hcounteren.CY` are set, + the `cycle` CSR (an alias of `mcycle`) is accessible to VU-mode. + + When `mcounteren.CY` and `hcounteren.CY` are set, + the `cycle` CSR (an alias of `mcycle`) is accessible to VS-mode. + + When `hcounteren.CY` is clear and `mcounteren.CY` is set, then any access to `cycle` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",cols="1,1,1,4,4"] + !=== + .2+h! [.rotate]#`hcounteren.CY`# .2+h! [.rotate]#`mcounteren.CY`# .2+h! [.rotate]#`scounteren.CY`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + definedBy: Zicntr + type(): | + if (HCOUNTENABLE_EN[0]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[0]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + TM: + location: 1 + description: | + When all of `scounteren.TM`, `mcounteren.TM`, and `hcounteren.TM` are set, + the `time` CSR (an alias of `mtime` memory-mapped CSR) is accessible to VU-mode. + + When `mcounteren.TM` and `hcounteren.TM` are set, + the `time` CSR (an alias of `mtime`) is accessible to VS-mode. + + When `hcounteren.TM` is clear and `mcounteren.TM` is set, then any access to `time` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.TM`# .2+h! [.rotate]#`mcounteren.TM`# .2+h! [.rotate]#`scounteren.TM`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + definedBy: Zicntr + type(): | + if (HCOUNTENABLE_EN[1]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[1]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + IR: + location: 2 + description: | + When all of `scounteren.IR`, `mcounteren.IR`, and `hcounteren.IR` are set, + the `instret` CSR (an alias of `minstret`) is accessible to VU-mode. + + When `mcounteren.IR` and `hcounteren.IR` are set, + the `instret` CSR (an alias of `minstret`) is accessible to VS-mode. + + When `hcounteren.IR` is clear and `mcounteren.IR` is set, then any access to `instret` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.IR`# .2+h! [.rotate]#`mcounteren.IR`# .2+h! [.rotate]#`scounteren.IR`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[2]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[2]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + <%- (3..31).each do |hpm_num| -%> + HPM<%= hpm_num %>: + location: <%= hpm_num %> + description: | + When all of `scounteren.HPM<%= hpm_num %>`, `mcounteren.HPM<%= hpm_num %>`, and `hcounteren.HPM<%= hpm_num %>` are set, + the `hpmcounter<%= hpm_num %>` CSR (an alias of `mhpmcounter<%= hpm_num %>`) is accessible to VU-mode. + + When `mcounteren.HPM<%= hpm_num %>` and `hcounteren.HPM<%= hpm_num %>` are set, + the `hpmcounter<%= hpm_num %>` CSR (an alias of `mhpmcounter<%= hpm_num %>`) is accessible to VS-mode. + + When `hcounteren.HPM<%= hpm_num %>` is clear and `mcounteren.HPM<%= hpm_num %>` is set, then any access to `hpmcounter<%= hpm_num %>` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`mcounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`scounteren.HPM<%= hpm_num %>`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[<%= hpm_num %>]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[<%= hpm_num %>]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + <%- end -%> diff --git a/arch/csr/H/hcounteren.yaml b/arch/csr/H/hcounteren.yaml index f9311b212..7623bce73 100644 --- a/arch/csr/H/hcounteren.yaml +++ b/arch/csr/H/hcounteren.yaml @@ -3,1201 +3,1203 @@ # WARNING: This file is auto-generated from arch/csr/H/hcounteren.layout -hcounteren: - long_name: Hypervisor Counter Enable - address: 0x606 - priv_mode: S - length: 32 - description: | - Together with `scounteren`, delegates control of the hardware performance-monitoring counters - to VS/VU-mode - - See `cycle` for a table describing how exceptions occur. - definedBy: H - fields: - CY: - location: 0 - description: | - When all of `scounteren.CY`, `mcounteren.CY`, and `hcounteren.CY` are set, - the `cycle` CSR (an alias of `mcycle`) is accessible to VU-mode. - - When `mcounteren.CY` and `hcounteren.CY` are set, - the `cycle` CSR (an alias of `mcycle`) is accessible to VS-mode. - - When `hcounteren.CY` is clear and `mcounteren.CY` is set, then any access to `cycle` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",cols="1,1,1,4,4"] - !=== - .2+h! [.rotate]#`hcounteren.CY`# .2+h! [.rotate]#`mcounteren.CY`# .2+h! [.rotate]#`scounteren.CY`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - definedBy: Zicntr - type(): | - if (HCOUNTENABLE_EN[0]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[0]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - TM: - location: 1 - description: | - When all of `scounteren.TM`, `mcounteren.TM`, and `hcounteren.TM` are set, - the `time` CSR (an alias of `mtime` memory-mapped CSR) is accessible to VU-mode. - - When `mcounteren.TM` and `hcounteren.TM` are set, - the `time` CSR (an alias of `mtime`) is accessible to VS-mode. - - When `hcounteren.TM` is clear and `mcounteren.TM` is set, then any access to `time` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.TM`# .2+h! [.rotate]#`mcounteren.TM`# .2+h! [.rotate]#`scounteren.TM`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - definedBy: Zicntr - type(): | - if (HCOUNTENABLE_EN[1]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[1]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - IR: - location: 2 - description: | - When all of `scounteren.IR`, `mcounteren.IR`, and `hcounteren.IR` are set, - the `instret` CSR (an alias of `minstret`) is accessible to VU-mode. - - When `mcounteren.IR` and `hcounteren.IR` are set, - the `instret` CSR (an alias of `minstret`) is accessible to VS-mode. - - When `hcounteren.IR` is clear and `mcounteren.IR` is set, then any access to `instret` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.IR`# .2+h! [.rotate]#`mcounteren.IR`# .2+h! [.rotate]#`scounteren.IR`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[2]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[2]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM3: - location: 3 - description: | - When all of `scounteren.HPM3`, `mcounteren.HPM3`, and `hcounteren.HPM3` are set, - the `hpmcounter3` CSR (an alias of `mhpmcounter3`) is accessible to VU-mode. - - When `mcounteren.HPM3` and `hcounteren.HPM3` are set, - the `hpmcounter3` CSR (an alias of `mhpmcounter3`) is accessible to VS-mode. - - When `hcounteren.HPM3` is clear and `mcounteren.HPM3` is set, then any access to `hpmcounter3` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM3`# .2+h! [.rotate]#`mcounteren.HPM3`# .2+h! [.rotate]#`scounteren.HPM3`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[3]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[3]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM4: - location: 4 - description: | - When all of `scounteren.HPM4`, `mcounteren.HPM4`, and `hcounteren.HPM4` are set, - the `hpmcounter4` CSR (an alias of `mhpmcounter4`) is accessible to VU-mode. - - When `mcounteren.HPM4` and `hcounteren.HPM4` are set, - the `hpmcounter4` CSR (an alias of `mhpmcounter4`) is accessible to VS-mode. - - When `hcounteren.HPM4` is clear and `mcounteren.HPM4` is set, then any access to `hpmcounter4` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM4`# .2+h! [.rotate]#`mcounteren.HPM4`# .2+h! [.rotate]#`scounteren.HPM4`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[4]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[4]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM5: - location: 5 - description: | - When all of `scounteren.HPM5`, `mcounteren.HPM5`, and `hcounteren.HPM5` are set, - the `hpmcounter5` CSR (an alias of `mhpmcounter5`) is accessible to VU-mode. - - When `mcounteren.HPM5` and `hcounteren.HPM5` are set, - the `hpmcounter5` CSR (an alias of `mhpmcounter5`) is accessible to VS-mode. - - When `hcounteren.HPM5` is clear and `mcounteren.HPM5` is set, then any access to `hpmcounter5` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM5`# .2+h! [.rotate]#`mcounteren.HPM5`# .2+h! [.rotate]#`scounteren.HPM5`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[5]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[5]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM6: - location: 6 - description: | - When all of `scounteren.HPM6`, `mcounteren.HPM6`, and `hcounteren.HPM6` are set, - the `hpmcounter6` CSR (an alias of `mhpmcounter6`) is accessible to VU-mode. - - When `mcounteren.HPM6` and `hcounteren.HPM6` are set, - the `hpmcounter6` CSR (an alias of `mhpmcounter6`) is accessible to VS-mode. - - When `hcounteren.HPM6` is clear and `mcounteren.HPM6` is set, then any access to `hpmcounter6` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM6`# .2+h! [.rotate]#`mcounteren.HPM6`# .2+h! [.rotate]#`scounteren.HPM6`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[6]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[6]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM7: - location: 7 - description: | - When all of `scounteren.HPM7`, `mcounteren.HPM7`, and `hcounteren.HPM7` are set, - the `hpmcounter7` CSR (an alias of `mhpmcounter7`) is accessible to VU-mode. - - When `mcounteren.HPM7` and `hcounteren.HPM7` are set, - the `hpmcounter7` CSR (an alias of `mhpmcounter7`) is accessible to VS-mode. - - When `hcounteren.HPM7` is clear and `mcounteren.HPM7` is set, then any access to `hpmcounter7` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM7`# .2+h! [.rotate]#`mcounteren.HPM7`# .2+h! [.rotate]#`scounteren.HPM7`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[7]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[7]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM8: - location: 8 - description: | - When all of `scounteren.HPM8`, `mcounteren.HPM8`, and `hcounteren.HPM8` are set, - the `hpmcounter8` CSR (an alias of `mhpmcounter8`) is accessible to VU-mode. - - When `mcounteren.HPM8` and `hcounteren.HPM8` are set, - the `hpmcounter8` CSR (an alias of `mhpmcounter8`) is accessible to VS-mode. - - When `hcounteren.HPM8` is clear and `mcounteren.HPM8` is set, then any access to `hpmcounter8` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM8`# .2+h! [.rotate]#`mcounteren.HPM8`# .2+h! [.rotate]#`scounteren.HPM8`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[8]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[8]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM9: - location: 9 - description: | - When all of `scounteren.HPM9`, `mcounteren.HPM9`, and `hcounteren.HPM9` are set, - the `hpmcounter9` CSR (an alias of `mhpmcounter9`) is accessible to VU-mode. - - When `mcounteren.HPM9` and `hcounteren.HPM9` are set, - the `hpmcounter9` CSR (an alias of `mhpmcounter9`) is accessible to VS-mode. - - When `hcounteren.HPM9` is clear and `mcounteren.HPM9` is set, then any access to `hpmcounter9` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM9`# .2+h! [.rotate]#`mcounteren.HPM9`# .2+h! [.rotate]#`scounteren.HPM9`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[9]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[9]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM10: - location: 10 - description: | - When all of `scounteren.HPM10`, `mcounteren.HPM10`, and `hcounteren.HPM10` are set, - the `hpmcounter10` CSR (an alias of `mhpmcounter10`) is accessible to VU-mode. - - When `mcounteren.HPM10` and `hcounteren.HPM10` are set, - the `hpmcounter10` CSR (an alias of `mhpmcounter10`) is accessible to VS-mode. - - When `hcounteren.HPM10` is clear and `mcounteren.HPM10` is set, then any access to `hpmcounter10` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM10`# .2+h! [.rotate]#`mcounteren.HPM10`# .2+h! [.rotate]#`scounteren.HPM10`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[10]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[10]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM11: - location: 11 - description: | - When all of `scounteren.HPM11`, `mcounteren.HPM11`, and `hcounteren.HPM11` are set, - the `hpmcounter11` CSR (an alias of `mhpmcounter11`) is accessible to VU-mode. - - When `mcounteren.HPM11` and `hcounteren.HPM11` are set, - the `hpmcounter11` CSR (an alias of `mhpmcounter11`) is accessible to VS-mode. - - When `hcounteren.HPM11` is clear and `mcounteren.HPM11` is set, then any access to `hpmcounter11` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM11`# .2+h! [.rotate]#`mcounteren.HPM11`# .2+h! [.rotate]#`scounteren.HPM11`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[11]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[11]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM12: - location: 12 - description: | - When all of `scounteren.HPM12`, `mcounteren.HPM12`, and `hcounteren.HPM12` are set, - the `hpmcounter12` CSR (an alias of `mhpmcounter12`) is accessible to VU-mode. - - When `mcounteren.HPM12` and `hcounteren.HPM12` are set, - the `hpmcounter12` CSR (an alias of `mhpmcounter12`) is accessible to VS-mode. - - When `hcounteren.HPM12` is clear and `mcounteren.HPM12` is set, then any access to `hpmcounter12` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM12`# .2+h! [.rotate]#`mcounteren.HPM12`# .2+h! [.rotate]#`scounteren.HPM12`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[12]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[12]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM13: - location: 13 - description: | - When all of `scounteren.HPM13`, `mcounteren.HPM13`, and `hcounteren.HPM13` are set, - the `hpmcounter13` CSR (an alias of `mhpmcounter13`) is accessible to VU-mode. - - When `mcounteren.HPM13` and `hcounteren.HPM13` are set, - the `hpmcounter13` CSR (an alias of `mhpmcounter13`) is accessible to VS-mode. - - When `hcounteren.HPM13` is clear and `mcounteren.HPM13` is set, then any access to `hpmcounter13` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM13`# .2+h! [.rotate]#`mcounteren.HPM13`# .2+h! [.rotate]#`scounteren.HPM13`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[13]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[13]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM14: - location: 14 - description: | - When all of `scounteren.HPM14`, `mcounteren.HPM14`, and `hcounteren.HPM14` are set, - the `hpmcounter14` CSR (an alias of `mhpmcounter14`) is accessible to VU-mode. - - When `mcounteren.HPM14` and `hcounteren.HPM14` are set, - the `hpmcounter14` CSR (an alias of `mhpmcounter14`) is accessible to VS-mode. - - When `hcounteren.HPM14` is clear and `mcounteren.HPM14` is set, then any access to `hpmcounter14` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM14`# .2+h! [.rotate]#`mcounteren.HPM14`# .2+h! [.rotate]#`scounteren.HPM14`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[14]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[14]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM15: - location: 15 - description: | - When all of `scounteren.HPM15`, `mcounteren.HPM15`, and `hcounteren.HPM15` are set, - the `hpmcounter15` CSR (an alias of `mhpmcounter15`) is accessible to VU-mode. - - When `mcounteren.HPM15` and `hcounteren.HPM15` are set, - the `hpmcounter15` CSR (an alias of `mhpmcounter15`) is accessible to VS-mode. - - When `hcounteren.HPM15` is clear and `mcounteren.HPM15` is set, then any access to `hpmcounter15` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM15`# .2+h! [.rotate]#`mcounteren.HPM15`# .2+h! [.rotate]#`scounteren.HPM15`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[15]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[15]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM16: - location: 16 - description: | - When all of `scounteren.HPM16`, `mcounteren.HPM16`, and `hcounteren.HPM16` are set, - the `hpmcounter16` CSR (an alias of `mhpmcounter16`) is accessible to VU-mode. - - When `mcounteren.HPM16` and `hcounteren.HPM16` are set, - the `hpmcounter16` CSR (an alias of `mhpmcounter16`) is accessible to VS-mode. - - When `hcounteren.HPM16` is clear and `mcounteren.HPM16` is set, then any access to `hpmcounter16` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM16`# .2+h! [.rotate]#`mcounteren.HPM16`# .2+h! [.rotate]#`scounteren.HPM16`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[16]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[16]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM17: - location: 17 - description: | - When all of `scounteren.HPM17`, `mcounteren.HPM17`, and `hcounteren.HPM17` are set, - the `hpmcounter17` CSR (an alias of `mhpmcounter17`) is accessible to VU-mode. - - When `mcounteren.HPM17` and `hcounteren.HPM17` are set, - the `hpmcounter17` CSR (an alias of `mhpmcounter17`) is accessible to VS-mode. - - When `hcounteren.HPM17` is clear and `mcounteren.HPM17` is set, then any access to `hpmcounter17` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM17`# .2+h! [.rotate]#`mcounteren.HPM17`# .2+h! [.rotate]#`scounteren.HPM17`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[17]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[17]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM18: - location: 18 - description: | - When all of `scounteren.HPM18`, `mcounteren.HPM18`, and `hcounteren.HPM18` are set, - the `hpmcounter18` CSR (an alias of `mhpmcounter18`) is accessible to VU-mode. - - When `mcounteren.HPM18` and `hcounteren.HPM18` are set, - the `hpmcounter18` CSR (an alias of `mhpmcounter18`) is accessible to VS-mode. - - When `hcounteren.HPM18` is clear and `mcounteren.HPM18` is set, then any access to `hpmcounter18` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM18`# .2+h! [.rotate]#`mcounteren.HPM18`# .2+h! [.rotate]#`scounteren.HPM18`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[18]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[18]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM19: - location: 19 - description: | - When all of `scounteren.HPM19`, `mcounteren.HPM19`, and `hcounteren.HPM19` are set, - the `hpmcounter19` CSR (an alias of `mhpmcounter19`) is accessible to VU-mode. - - When `mcounteren.HPM19` and `hcounteren.HPM19` are set, - the `hpmcounter19` CSR (an alias of `mhpmcounter19`) is accessible to VS-mode. - - When `hcounteren.HPM19` is clear and `mcounteren.HPM19` is set, then any access to `hpmcounter19` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM19`# .2+h! [.rotate]#`mcounteren.HPM19`# .2+h! [.rotate]#`scounteren.HPM19`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[19]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[19]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM20: - location: 20 - description: | - When all of `scounteren.HPM20`, `mcounteren.HPM20`, and `hcounteren.HPM20` are set, - the `hpmcounter20` CSR (an alias of `mhpmcounter20`) is accessible to VU-mode. - - When `mcounteren.HPM20` and `hcounteren.HPM20` are set, - the `hpmcounter20` CSR (an alias of `mhpmcounter20`) is accessible to VS-mode. - - When `hcounteren.HPM20` is clear and `mcounteren.HPM20` is set, then any access to `hpmcounter20` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM20`# .2+h! [.rotate]#`mcounteren.HPM20`# .2+h! [.rotate]#`scounteren.HPM20`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[20]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[20]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM21: - location: 21 - description: | - When all of `scounteren.HPM21`, `mcounteren.HPM21`, and `hcounteren.HPM21` are set, - the `hpmcounter21` CSR (an alias of `mhpmcounter21`) is accessible to VU-mode. - - When `mcounteren.HPM21` and `hcounteren.HPM21` are set, - the `hpmcounter21` CSR (an alias of `mhpmcounter21`) is accessible to VS-mode. - - When `hcounteren.HPM21` is clear and `mcounteren.HPM21` is set, then any access to `hpmcounter21` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM21`# .2+h! [.rotate]#`mcounteren.HPM21`# .2+h! [.rotate]#`scounteren.HPM21`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[21]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[21]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM22: - location: 22 - description: | - When all of `scounteren.HPM22`, `mcounteren.HPM22`, and `hcounteren.HPM22` are set, - the `hpmcounter22` CSR (an alias of `mhpmcounter22`) is accessible to VU-mode. - - When `mcounteren.HPM22` and `hcounteren.HPM22` are set, - the `hpmcounter22` CSR (an alias of `mhpmcounter22`) is accessible to VS-mode. - - When `hcounteren.HPM22` is clear and `mcounteren.HPM22` is set, then any access to `hpmcounter22` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM22`# .2+h! [.rotate]#`mcounteren.HPM22`# .2+h! [.rotate]#`scounteren.HPM22`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[22]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[22]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM23: - location: 23 - description: | - When all of `scounteren.HPM23`, `mcounteren.HPM23`, and `hcounteren.HPM23` are set, - the `hpmcounter23` CSR (an alias of `mhpmcounter23`) is accessible to VU-mode. - - When `mcounteren.HPM23` and `hcounteren.HPM23` are set, - the `hpmcounter23` CSR (an alias of `mhpmcounter23`) is accessible to VS-mode. - - When `hcounteren.HPM23` is clear and `mcounteren.HPM23` is set, then any access to `hpmcounter23` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM23`# .2+h! [.rotate]#`mcounteren.HPM23`# .2+h! [.rotate]#`scounteren.HPM23`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[23]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[23]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM24: - location: 24 - description: | - When all of `scounteren.HPM24`, `mcounteren.HPM24`, and `hcounteren.HPM24` are set, - the `hpmcounter24` CSR (an alias of `mhpmcounter24`) is accessible to VU-mode. - - When `mcounteren.HPM24` and `hcounteren.HPM24` are set, - the `hpmcounter24` CSR (an alias of `mhpmcounter24`) is accessible to VS-mode. - - When `hcounteren.HPM24` is clear and `mcounteren.HPM24` is set, then any access to `hpmcounter24` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM24`# .2+h! [.rotate]#`mcounteren.HPM24`# .2+h! [.rotate]#`scounteren.HPM24`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[24]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[24]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM25: - location: 25 - description: | - When all of `scounteren.HPM25`, `mcounteren.HPM25`, and `hcounteren.HPM25` are set, - the `hpmcounter25` CSR (an alias of `mhpmcounter25`) is accessible to VU-mode. - - When `mcounteren.HPM25` and `hcounteren.HPM25` are set, - the `hpmcounter25` CSR (an alias of `mhpmcounter25`) is accessible to VS-mode. - - When `hcounteren.HPM25` is clear and `mcounteren.HPM25` is set, then any access to `hpmcounter25` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM25`# .2+h! [.rotate]#`mcounteren.HPM25`# .2+h! [.rotate]#`scounteren.HPM25`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[25]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[25]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM26: - location: 26 - description: | - When all of `scounteren.HPM26`, `mcounteren.HPM26`, and `hcounteren.HPM26` are set, - the `hpmcounter26` CSR (an alias of `mhpmcounter26`) is accessible to VU-mode. - - When `mcounteren.HPM26` and `hcounteren.HPM26` are set, - the `hpmcounter26` CSR (an alias of `mhpmcounter26`) is accessible to VS-mode. - - When `hcounteren.HPM26` is clear and `mcounteren.HPM26` is set, then any access to `hpmcounter26` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM26`# .2+h! [.rotate]#`mcounteren.HPM26`# .2+h! [.rotate]#`scounteren.HPM26`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[26]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[26]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM27: - location: 27 - description: | - When all of `scounteren.HPM27`, `mcounteren.HPM27`, and `hcounteren.HPM27` are set, - the `hpmcounter27` CSR (an alias of `mhpmcounter27`) is accessible to VU-mode. - - When `mcounteren.HPM27` and `hcounteren.HPM27` are set, - the `hpmcounter27` CSR (an alias of `mhpmcounter27`) is accessible to VS-mode. - - When `hcounteren.HPM27` is clear and `mcounteren.HPM27` is set, then any access to `hpmcounter27` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM27`# .2+h! [.rotate]#`mcounteren.HPM27`# .2+h! [.rotate]#`scounteren.HPM27`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[27]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[27]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM28: - location: 28 - description: | - When all of `scounteren.HPM28`, `mcounteren.HPM28`, and `hcounteren.HPM28` are set, - the `hpmcounter28` CSR (an alias of `mhpmcounter28`) is accessible to VU-mode. - - When `mcounteren.HPM28` and `hcounteren.HPM28` are set, - the `hpmcounter28` CSR (an alias of `mhpmcounter28`) is accessible to VS-mode. - - When `hcounteren.HPM28` is clear and `mcounteren.HPM28` is set, then any access to `hpmcounter28` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM28`# .2+h! [.rotate]#`mcounteren.HPM28`# .2+h! [.rotate]#`scounteren.HPM28`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[28]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[28]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM29: - location: 29 - description: | - When all of `scounteren.HPM29`, `mcounteren.HPM29`, and `hcounteren.HPM29` are set, - the `hpmcounter29` CSR (an alias of `mhpmcounter29`) is accessible to VU-mode. - - When `mcounteren.HPM29` and `hcounteren.HPM29` are set, - the `hpmcounter29` CSR (an alias of `mhpmcounter29`) is accessible to VS-mode. - - When `hcounteren.HPM29` is clear and `mcounteren.HPM29` is set, then any access to `hpmcounter29` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM29`# .2+h! [.rotate]#`mcounteren.HPM29`# .2+h! [.rotate]#`scounteren.HPM29`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[29]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[29]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM30: - location: 30 - description: | - When all of `scounteren.HPM30`, `mcounteren.HPM30`, and `hcounteren.HPM30` are set, - the `hpmcounter30` CSR (an alias of `mhpmcounter30`) is accessible to VU-mode. - - When `mcounteren.HPM30` and `hcounteren.HPM30` are set, - the `hpmcounter30` CSR (an alias of `mhpmcounter30`) is accessible to VS-mode. - - When `hcounteren.HPM30` is clear and `mcounteren.HPM30` is set, then any access to `hpmcounter30` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM30`# .2+h! [.rotate]#`mcounteren.HPM30`# .2+h! [.rotate]#`scounteren.HPM30`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[30]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[30]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM31: - location: 31 - description: | - When all of `scounteren.HPM31`, `mcounteren.HPM31`, and `hcounteren.HPM31` are set, - the `hpmcounter31` CSR (an alias of `mhpmcounter31`) is accessible to VU-mode. - - When `mcounteren.HPM31` and `hcounteren.HPM31` are set, - the `hpmcounter31` CSR (an alias of `mhpmcounter31`) is accessible to VS-mode. - - When `hcounteren.HPM31` is clear and `mcounteren.HPM31` is set, then any access to `hpmcounter31` in - VU-mode or VS-mode causes a VirtualInstruction execption. - - Summary: - - [separator="!",%autowidth] - !=== - .2+h! [.rotate]#`hcounteren.HPM31`# .2+h! [.rotate]#`mcounteren.HPM31`# .2+h! [.rotate]#`scounteren.HPM31`# 2+^.>! `cycle` access behavior - .>h! VS-mode .>h! VU-mode - - ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! allowed ! allowed - !=== - type(): | - if (HCOUNTENABLE_EN[31]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HCOUNTENABLE_EN[31]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: hcounteren +long_name: Hypervisor Counter Enable +address: 0x606 +priv_mode: S +length: 32 +description: | + Together with `scounteren`, delegates control of the hardware performance-monitoring counters + to VS/VU-mode + + See `cycle` for a table describing how exceptions occur. +definedBy: H +fields: + CY: + location: 0 + description: | + When all of `scounteren.CY`, `mcounteren.CY`, and `hcounteren.CY` are set, + the `cycle` CSR (an alias of `mcycle`) is accessible to VU-mode. + + When `mcounteren.CY` and `hcounteren.CY` are set, + the `cycle` CSR (an alias of `mcycle`) is accessible to VS-mode. + + When `hcounteren.CY` is clear and `mcounteren.CY` is set, then any access to `cycle` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",cols="1,1,1,4,4"] + !=== + .2+h! [.rotate]#`hcounteren.CY`# .2+h! [.rotate]#`mcounteren.CY`# .2+h! [.rotate]#`scounteren.CY`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + definedBy: Zicntr + type(): | + if (HCOUNTENABLE_EN[0]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[0]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + TM: + location: 1 + description: | + When all of `scounteren.TM`, `mcounteren.TM`, and `hcounteren.TM` are set, + the `time` CSR (an alias of `mtime` memory-mapped CSR) is accessible to VU-mode. + + When `mcounteren.TM` and `hcounteren.TM` are set, + the `time` CSR (an alias of `mtime`) is accessible to VS-mode. + + When `hcounteren.TM` is clear and `mcounteren.TM` is set, then any access to `time` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.TM`# .2+h! [.rotate]#`mcounteren.TM`# .2+h! [.rotate]#`scounteren.TM`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + definedBy: Zicntr + type(): | + if (HCOUNTENABLE_EN[1]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[1]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + IR: + location: 2 + description: | + When all of `scounteren.IR`, `mcounteren.IR`, and `hcounteren.IR` are set, + the `instret` CSR (an alias of `minstret`) is accessible to VU-mode. + + When `mcounteren.IR` and `hcounteren.IR` are set, + the `instret` CSR (an alias of `minstret`) is accessible to VS-mode. + + When `hcounteren.IR` is clear and `mcounteren.IR` is set, then any access to `instret` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.IR`# .2+h! [.rotate]#`mcounteren.IR`# .2+h! [.rotate]#`scounteren.IR`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[2]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[2]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM3: + location: 3 + description: | + When all of `scounteren.HPM3`, `mcounteren.HPM3`, and `hcounteren.HPM3` are set, + the `hpmcounter3` CSR (an alias of `mhpmcounter3`) is accessible to VU-mode. + + When `mcounteren.HPM3` and `hcounteren.HPM3` are set, + the `hpmcounter3` CSR (an alias of `mhpmcounter3`) is accessible to VS-mode. + + When `hcounteren.HPM3` is clear and `mcounteren.HPM3` is set, then any access to `hpmcounter3` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM3`# .2+h! [.rotate]#`mcounteren.HPM3`# .2+h! [.rotate]#`scounteren.HPM3`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[3]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[3]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM4: + location: 4 + description: | + When all of `scounteren.HPM4`, `mcounteren.HPM4`, and `hcounteren.HPM4` are set, + the `hpmcounter4` CSR (an alias of `mhpmcounter4`) is accessible to VU-mode. + + When `mcounteren.HPM4` and `hcounteren.HPM4` are set, + the `hpmcounter4` CSR (an alias of `mhpmcounter4`) is accessible to VS-mode. + + When `hcounteren.HPM4` is clear and `mcounteren.HPM4` is set, then any access to `hpmcounter4` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM4`# .2+h! [.rotate]#`mcounteren.HPM4`# .2+h! [.rotate]#`scounteren.HPM4`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[4]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[4]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM5: + location: 5 + description: | + When all of `scounteren.HPM5`, `mcounteren.HPM5`, and `hcounteren.HPM5` are set, + the `hpmcounter5` CSR (an alias of `mhpmcounter5`) is accessible to VU-mode. + + When `mcounteren.HPM5` and `hcounteren.HPM5` are set, + the `hpmcounter5` CSR (an alias of `mhpmcounter5`) is accessible to VS-mode. + + When `hcounteren.HPM5` is clear and `mcounteren.HPM5` is set, then any access to `hpmcounter5` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM5`# .2+h! [.rotate]#`mcounteren.HPM5`# .2+h! [.rotate]#`scounteren.HPM5`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[5]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[5]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM6: + location: 6 + description: | + When all of `scounteren.HPM6`, `mcounteren.HPM6`, and `hcounteren.HPM6` are set, + the `hpmcounter6` CSR (an alias of `mhpmcounter6`) is accessible to VU-mode. + + When `mcounteren.HPM6` and `hcounteren.HPM6` are set, + the `hpmcounter6` CSR (an alias of `mhpmcounter6`) is accessible to VS-mode. + + When `hcounteren.HPM6` is clear and `mcounteren.HPM6` is set, then any access to `hpmcounter6` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM6`# .2+h! [.rotate]#`mcounteren.HPM6`# .2+h! [.rotate]#`scounteren.HPM6`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[6]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[6]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM7: + location: 7 + description: | + When all of `scounteren.HPM7`, `mcounteren.HPM7`, and `hcounteren.HPM7` are set, + the `hpmcounter7` CSR (an alias of `mhpmcounter7`) is accessible to VU-mode. + + When `mcounteren.HPM7` and `hcounteren.HPM7` are set, + the `hpmcounter7` CSR (an alias of `mhpmcounter7`) is accessible to VS-mode. + + When `hcounteren.HPM7` is clear and `mcounteren.HPM7` is set, then any access to `hpmcounter7` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM7`# .2+h! [.rotate]#`mcounteren.HPM7`# .2+h! [.rotate]#`scounteren.HPM7`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[7]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[7]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM8: + location: 8 + description: | + When all of `scounteren.HPM8`, `mcounteren.HPM8`, and `hcounteren.HPM8` are set, + the `hpmcounter8` CSR (an alias of `mhpmcounter8`) is accessible to VU-mode. + + When `mcounteren.HPM8` and `hcounteren.HPM8` are set, + the `hpmcounter8` CSR (an alias of `mhpmcounter8`) is accessible to VS-mode. + + When `hcounteren.HPM8` is clear and `mcounteren.HPM8` is set, then any access to `hpmcounter8` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM8`# .2+h! [.rotate]#`mcounteren.HPM8`# .2+h! [.rotate]#`scounteren.HPM8`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[8]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[8]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM9: + location: 9 + description: | + When all of `scounteren.HPM9`, `mcounteren.HPM9`, and `hcounteren.HPM9` are set, + the `hpmcounter9` CSR (an alias of `mhpmcounter9`) is accessible to VU-mode. + + When `mcounteren.HPM9` and `hcounteren.HPM9` are set, + the `hpmcounter9` CSR (an alias of `mhpmcounter9`) is accessible to VS-mode. + + When `hcounteren.HPM9` is clear and `mcounteren.HPM9` is set, then any access to `hpmcounter9` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM9`# .2+h! [.rotate]#`mcounteren.HPM9`# .2+h! [.rotate]#`scounteren.HPM9`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[9]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[9]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM10: + location: 10 + description: | + When all of `scounteren.HPM10`, `mcounteren.HPM10`, and `hcounteren.HPM10` are set, + the `hpmcounter10` CSR (an alias of `mhpmcounter10`) is accessible to VU-mode. + + When `mcounteren.HPM10` and `hcounteren.HPM10` are set, + the `hpmcounter10` CSR (an alias of `mhpmcounter10`) is accessible to VS-mode. + + When `hcounteren.HPM10` is clear and `mcounteren.HPM10` is set, then any access to `hpmcounter10` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM10`# .2+h! [.rotate]#`mcounteren.HPM10`# .2+h! [.rotate]#`scounteren.HPM10`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[10]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[10]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM11: + location: 11 + description: | + When all of `scounteren.HPM11`, `mcounteren.HPM11`, and `hcounteren.HPM11` are set, + the `hpmcounter11` CSR (an alias of `mhpmcounter11`) is accessible to VU-mode. + + When `mcounteren.HPM11` and `hcounteren.HPM11` are set, + the `hpmcounter11` CSR (an alias of `mhpmcounter11`) is accessible to VS-mode. + + When `hcounteren.HPM11` is clear and `mcounteren.HPM11` is set, then any access to `hpmcounter11` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM11`# .2+h! [.rotate]#`mcounteren.HPM11`# .2+h! [.rotate]#`scounteren.HPM11`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[11]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[11]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM12: + location: 12 + description: | + When all of `scounteren.HPM12`, `mcounteren.HPM12`, and `hcounteren.HPM12` are set, + the `hpmcounter12` CSR (an alias of `mhpmcounter12`) is accessible to VU-mode. + + When `mcounteren.HPM12` and `hcounteren.HPM12` are set, + the `hpmcounter12` CSR (an alias of `mhpmcounter12`) is accessible to VS-mode. + + When `hcounteren.HPM12` is clear and `mcounteren.HPM12` is set, then any access to `hpmcounter12` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM12`# .2+h! [.rotate]#`mcounteren.HPM12`# .2+h! [.rotate]#`scounteren.HPM12`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[12]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[12]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM13: + location: 13 + description: | + When all of `scounteren.HPM13`, `mcounteren.HPM13`, and `hcounteren.HPM13` are set, + the `hpmcounter13` CSR (an alias of `mhpmcounter13`) is accessible to VU-mode. + + When `mcounteren.HPM13` and `hcounteren.HPM13` are set, + the `hpmcounter13` CSR (an alias of `mhpmcounter13`) is accessible to VS-mode. + + When `hcounteren.HPM13` is clear and `mcounteren.HPM13` is set, then any access to `hpmcounter13` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM13`# .2+h! [.rotate]#`mcounteren.HPM13`# .2+h! [.rotate]#`scounteren.HPM13`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[13]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[13]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM14: + location: 14 + description: | + When all of `scounteren.HPM14`, `mcounteren.HPM14`, and `hcounteren.HPM14` are set, + the `hpmcounter14` CSR (an alias of `mhpmcounter14`) is accessible to VU-mode. + + When `mcounteren.HPM14` and `hcounteren.HPM14` are set, + the `hpmcounter14` CSR (an alias of `mhpmcounter14`) is accessible to VS-mode. + + When `hcounteren.HPM14` is clear and `mcounteren.HPM14` is set, then any access to `hpmcounter14` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM14`# .2+h! [.rotate]#`mcounteren.HPM14`# .2+h! [.rotate]#`scounteren.HPM14`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[14]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[14]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM15: + location: 15 + description: | + When all of `scounteren.HPM15`, `mcounteren.HPM15`, and `hcounteren.HPM15` are set, + the `hpmcounter15` CSR (an alias of `mhpmcounter15`) is accessible to VU-mode. + + When `mcounteren.HPM15` and `hcounteren.HPM15` are set, + the `hpmcounter15` CSR (an alias of `mhpmcounter15`) is accessible to VS-mode. + + When `hcounteren.HPM15` is clear and `mcounteren.HPM15` is set, then any access to `hpmcounter15` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM15`# .2+h! [.rotate]#`mcounteren.HPM15`# .2+h! [.rotate]#`scounteren.HPM15`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[15]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[15]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM16: + location: 16 + description: | + When all of `scounteren.HPM16`, `mcounteren.HPM16`, and `hcounteren.HPM16` are set, + the `hpmcounter16` CSR (an alias of `mhpmcounter16`) is accessible to VU-mode. + + When `mcounteren.HPM16` and `hcounteren.HPM16` are set, + the `hpmcounter16` CSR (an alias of `mhpmcounter16`) is accessible to VS-mode. + + When `hcounteren.HPM16` is clear and `mcounteren.HPM16` is set, then any access to `hpmcounter16` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM16`# .2+h! [.rotate]#`mcounteren.HPM16`# .2+h! [.rotate]#`scounteren.HPM16`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[16]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[16]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM17: + location: 17 + description: | + When all of `scounteren.HPM17`, `mcounteren.HPM17`, and `hcounteren.HPM17` are set, + the `hpmcounter17` CSR (an alias of `mhpmcounter17`) is accessible to VU-mode. + + When `mcounteren.HPM17` and `hcounteren.HPM17` are set, + the `hpmcounter17` CSR (an alias of `mhpmcounter17`) is accessible to VS-mode. + + When `hcounteren.HPM17` is clear and `mcounteren.HPM17` is set, then any access to `hpmcounter17` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM17`# .2+h! [.rotate]#`mcounteren.HPM17`# .2+h! [.rotate]#`scounteren.HPM17`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[17]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[17]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM18: + location: 18 + description: | + When all of `scounteren.HPM18`, `mcounteren.HPM18`, and `hcounteren.HPM18` are set, + the `hpmcounter18` CSR (an alias of `mhpmcounter18`) is accessible to VU-mode. + + When `mcounteren.HPM18` and `hcounteren.HPM18` are set, + the `hpmcounter18` CSR (an alias of `mhpmcounter18`) is accessible to VS-mode. + + When `hcounteren.HPM18` is clear and `mcounteren.HPM18` is set, then any access to `hpmcounter18` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM18`# .2+h! [.rotate]#`mcounteren.HPM18`# .2+h! [.rotate]#`scounteren.HPM18`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[18]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[18]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM19: + location: 19 + description: | + When all of `scounteren.HPM19`, `mcounteren.HPM19`, and `hcounteren.HPM19` are set, + the `hpmcounter19` CSR (an alias of `mhpmcounter19`) is accessible to VU-mode. + + When `mcounteren.HPM19` and `hcounteren.HPM19` are set, + the `hpmcounter19` CSR (an alias of `mhpmcounter19`) is accessible to VS-mode. + + When `hcounteren.HPM19` is clear and `mcounteren.HPM19` is set, then any access to `hpmcounter19` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM19`# .2+h! [.rotate]#`mcounteren.HPM19`# .2+h! [.rotate]#`scounteren.HPM19`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[19]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[19]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM20: + location: 20 + description: | + When all of `scounteren.HPM20`, `mcounteren.HPM20`, and `hcounteren.HPM20` are set, + the `hpmcounter20` CSR (an alias of `mhpmcounter20`) is accessible to VU-mode. + + When `mcounteren.HPM20` and `hcounteren.HPM20` are set, + the `hpmcounter20` CSR (an alias of `mhpmcounter20`) is accessible to VS-mode. + + When `hcounteren.HPM20` is clear and `mcounteren.HPM20` is set, then any access to `hpmcounter20` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM20`# .2+h! [.rotate]#`mcounteren.HPM20`# .2+h! [.rotate]#`scounteren.HPM20`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[20]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[20]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM21: + location: 21 + description: | + When all of `scounteren.HPM21`, `mcounteren.HPM21`, and `hcounteren.HPM21` are set, + the `hpmcounter21` CSR (an alias of `mhpmcounter21`) is accessible to VU-mode. + + When `mcounteren.HPM21` and `hcounteren.HPM21` are set, + the `hpmcounter21` CSR (an alias of `mhpmcounter21`) is accessible to VS-mode. + + When `hcounteren.HPM21` is clear and `mcounteren.HPM21` is set, then any access to `hpmcounter21` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM21`# .2+h! [.rotate]#`mcounteren.HPM21`# .2+h! [.rotate]#`scounteren.HPM21`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[21]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[21]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM22: + location: 22 + description: | + When all of `scounteren.HPM22`, `mcounteren.HPM22`, and `hcounteren.HPM22` are set, + the `hpmcounter22` CSR (an alias of `mhpmcounter22`) is accessible to VU-mode. + + When `mcounteren.HPM22` and `hcounteren.HPM22` are set, + the `hpmcounter22` CSR (an alias of `mhpmcounter22`) is accessible to VS-mode. + + When `hcounteren.HPM22` is clear and `mcounteren.HPM22` is set, then any access to `hpmcounter22` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM22`# .2+h! [.rotate]#`mcounteren.HPM22`# .2+h! [.rotate]#`scounteren.HPM22`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[22]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[22]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM23: + location: 23 + description: | + When all of `scounteren.HPM23`, `mcounteren.HPM23`, and `hcounteren.HPM23` are set, + the `hpmcounter23` CSR (an alias of `mhpmcounter23`) is accessible to VU-mode. + + When `mcounteren.HPM23` and `hcounteren.HPM23` are set, + the `hpmcounter23` CSR (an alias of `mhpmcounter23`) is accessible to VS-mode. + + When `hcounteren.HPM23` is clear and `mcounteren.HPM23` is set, then any access to `hpmcounter23` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM23`# .2+h! [.rotate]#`mcounteren.HPM23`# .2+h! [.rotate]#`scounteren.HPM23`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[23]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[23]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM24: + location: 24 + description: | + When all of `scounteren.HPM24`, `mcounteren.HPM24`, and `hcounteren.HPM24` are set, + the `hpmcounter24` CSR (an alias of `mhpmcounter24`) is accessible to VU-mode. + + When `mcounteren.HPM24` and `hcounteren.HPM24` are set, + the `hpmcounter24` CSR (an alias of `mhpmcounter24`) is accessible to VS-mode. + + When `hcounteren.HPM24` is clear and `mcounteren.HPM24` is set, then any access to `hpmcounter24` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM24`# .2+h! [.rotate]#`mcounteren.HPM24`# .2+h! [.rotate]#`scounteren.HPM24`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[24]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[24]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM25: + location: 25 + description: | + When all of `scounteren.HPM25`, `mcounteren.HPM25`, and `hcounteren.HPM25` are set, + the `hpmcounter25` CSR (an alias of `mhpmcounter25`) is accessible to VU-mode. + + When `mcounteren.HPM25` and `hcounteren.HPM25` are set, + the `hpmcounter25` CSR (an alias of `mhpmcounter25`) is accessible to VS-mode. + + When `hcounteren.HPM25` is clear and `mcounteren.HPM25` is set, then any access to `hpmcounter25` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM25`# .2+h! [.rotate]#`mcounteren.HPM25`# .2+h! [.rotate]#`scounteren.HPM25`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[25]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[25]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM26: + location: 26 + description: | + When all of `scounteren.HPM26`, `mcounteren.HPM26`, and `hcounteren.HPM26` are set, + the `hpmcounter26` CSR (an alias of `mhpmcounter26`) is accessible to VU-mode. + + When `mcounteren.HPM26` and `hcounteren.HPM26` are set, + the `hpmcounter26` CSR (an alias of `mhpmcounter26`) is accessible to VS-mode. + + When `hcounteren.HPM26` is clear and `mcounteren.HPM26` is set, then any access to `hpmcounter26` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM26`# .2+h! [.rotate]#`mcounteren.HPM26`# .2+h! [.rotate]#`scounteren.HPM26`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[26]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[26]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM27: + location: 27 + description: | + When all of `scounteren.HPM27`, `mcounteren.HPM27`, and `hcounteren.HPM27` are set, + the `hpmcounter27` CSR (an alias of `mhpmcounter27`) is accessible to VU-mode. + + When `mcounteren.HPM27` and `hcounteren.HPM27` are set, + the `hpmcounter27` CSR (an alias of `mhpmcounter27`) is accessible to VS-mode. + + When `hcounteren.HPM27` is clear and `mcounteren.HPM27` is set, then any access to `hpmcounter27` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM27`# .2+h! [.rotate]#`mcounteren.HPM27`# .2+h! [.rotate]#`scounteren.HPM27`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[27]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[27]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM28: + location: 28 + description: | + When all of `scounteren.HPM28`, `mcounteren.HPM28`, and `hcounteren.HPM28` are set, + the `hpmcounter28` CSR (an alias of `mhpmcounter28`) is accessible to VU-mode. + + When `mcounteren.HPM28` and `hcounteren.HPM28` are set, + the `hpmcounter28` CSR (an alias of `mhpmcounter28`) is accessible to VS-mode. + + When `hcounteren.HPM28` is clear and `mcounteren.HPM28` is set, then any access to `hpmcounter28` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM28`# .2+h! [.rotate]#`mcounteren.HPM28`# .2+h! [.rotate]#`scounteren.HPM28`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[28]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[28]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM29: + location: 29 + description: | + When all of `scounteren.HPM29`, `mcounteren.HPM29`, and `hcounteren.HPM29` are set, + the `hpmcounter29` CSR (an alias of `mhpmcounter29`) is accessible to VU-mode. + + When `mcounteren.HPM29` and `hcounteren.HPM29` are set, + the `hpmcounter29` CSR (an alias of `mhpmcounter29`) is accessible to VS-mode. + + When `hcounteren.HPM29` is clear and `mcounteren.HPM29` is set, then any access to `hpmcounter29` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM29`# .2+h! [.rotate]#`mcounteren.HPM29`# .2+h! [.rotate]#`scounteren.HPM29`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[29]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[29]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM30: + location: 30 + description: | + When all of `scounteren.HPM30`, `mcounteren.HPM30`, and `hcounteren.HPM30` are set, + the `hpmcounter30` CSR (an alias of `mhpmcounter30`) is accessible to VU-mode. + + When `mcounteren.HPM30` and `hcounteren.HPM30` are set, + the `hpmcounter30` CSR (an alias of `mhpmcounter30`) is accessible to VS-mode. + + When `hcounteren.HPM30` is clear and `mcounteren.HPM30` is set, then any access to `hpmcounter30` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM30`# .2+h! [.rotate]#`mcounteren.HPM30`# .2+h! [.rotate]#`scounteren.HPM30`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[30]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[30]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM31: + location: 31 + description: | + When all of `scounteren.HPM31`, `mcounteren.HPM31`, and `hcounteren.HPM31` are set, + the `hpmcounter31` CSR (an alias of `mhpmcounter31`) is accessible to VU-mode. + + When `mcounteren.HPM31` and `hcounteren.HPM31` are set, + the `hpmcounter31` CSR (an alias of `mhpmcounter31`) is accessible to VS-mode. + + When `hcounteren.HPM31` is clear and `mcounteren.HPM31` is set, then any access to `hpmcounter31` in + VU-mode or VS-mode causes a VirtualInstruction execption. + + Summary: + + [separator="!",%autowidth] + !=== + .2+h! [.rotate]#`hcounteren.HPM31`# .2+h! [.rotate]#`mcounteren.HPM31`# .2+h! [.rotate]#`scounteren.HPM31`# 2+^.>! `cycle` access behavior + .>h! VS-mode .>h! VU-mode + + ! 0 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 0 ! 1 ! - ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 1 ! 0 ! allowed ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! allowed ! allowed + !=== + type(): | + if (HCOUNTENABLE_EN[31]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HCOUNTENABLE_EN[31]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/H/henvcfg.yaml b/arch/csr/H/henvcfg.yaml index 092ed3554..8086aec41 100644 --- a/arch/csr/H/henvcfg.yaml +++ b/arch/csr/H/henvcfg.yaml @@ -1,288 +1,290 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -henvcfg: - address: 0x60A - long_name: Hypervisor Environment Configuration - description: | - The henvcfg CSR is a 64-bit read/write register that controls certain characteristics of the - execution environment when virtualization mode V=1. - - If bit `henvcfg.FIOM` (Fence of I/O implies Memory) is set to one in henvcfg, `fence` - instructions executed when V=1 are modified so the requirement to order accesses to device I/O - implies also the requirement to order main memory accesses. - - <> details the modified interpretation of FENCE instruction bits PI, PO, SI, and SO when - FIOM=1 and V=1. - - Similarly, when `henvcfg.FIOM`=1 and V=1, if an atomic instruction that accesses a - region ordered as device I/O has its _aq_ and/or _rl_ bit set, then that - instruction is ordered as though it accesses both device I/O and memory. - - [[henvcfg-FIOM]] - .Modified interpretation of FENCE predecessor and successor sets when FIOM=1 and virtualization mode V=1. - [%autowidth,float="center",align="center",cols="^,<",options="header"] - |=== - |Instruction bit |Meaning when set - |PI + - PO - |Predecessor device input and memory reads (PR implied) + - Predecessor device output and memory writes (PW implied) - |SI + - SO - |Successor device input and memory reads (SR implied) + - Successor device output and memory writes (SW implied) - |=== - - The PBMTE bit controls whether the Svpbmt extension is available for use - in VS-stage address translation. When PBMTE=1, Svpbmt is available for - VS-stage address translation. When PBMTE=0, the implementation behaves - as though Svpbmt were not implemented for VS-stage address translation. - If Svpbmt is not implemented, PBMTE is read-only zero. - - If the Svadu extension is implemented, the ADUE bit controls whether hardware - updating of PTE A/D bits is enabled for VS-stage address translation. - When ADUE=1, hardware updating of PTE A/D bits is enabled during VS-stage - address translation, and the implementation behaves as though the Svade - extension were not implemented for VS-mode address translation. - When ADUE=0, the implementation behaves as though Svade were implemented for - VS-stage address translation. - If Svadu is not implemented, ADUE is read-only zero. - - The definition of the STCE field is furnished by the Sstc extension. - - The definition of the CBZE field is furnished by the Zicboz extension. - - The definitions of the CBCFE and CBIE fields are furnished by the Zicbom extension. - - The definition of the PMM field will be furnished by the forthcoming - Ssnpm extension. Its allocation within `henvcfg` may change prior to the - ratification of that extension. - - The Zicfilp extension adds the `LPE` field in `henvcfg`. When the `LPE` field - is set to 1, the Zicfilp extension is enabled in VS-mode. When the `LPE` field - is 0, the Zicfilp extension is not enabled in VS-mode and the following rules - apply to VS-mode: - - * The hart does not update the `ELP` state; it remains as `NO_LP_EXPECTED`. - * The `LPAD` instruction operates as a no-op. - - The Zicfiss extension adds the `SSE` field in `henvcfg`. If the `SSE` field is - set to 1, the Zicfiss extension is activated in VS-mode. When the `SSE` field is - 0, the Zicfiss extension remains inactive in VS-mode, and the following rules - apply when `V=1`: - - * 32-bit Zicfiss instructions will revert to their behavior as defined by Zimop. - * 16-bit Zicfiss instructions will revert to their behavior as defined by Zcmop. - * The `pte.xwr=010b` encoding in VS-stage page tables becomes reserved. - * The `senvcfg.SSE` field will read as zero and is read-only. - * When `menvcfg.SSE` is one, `SSAMOSWAP.W/D` raises a virtual instruction - exception. - - The Ssdbltrp extension adds the double-trap-enable (`DTE`) field in `henvcfg`. - When `henvcfg.DTE` is zero, the implementation behaves as though Ssdbltrp is not - implemented for VS-mode and the `vsstatus.SDT` bit is read-only zero. - - When XLEN=32, `henvcfgh` is a - 32-bit read/write register that aliases bits 63:32 - of `henvcfg`. Register `henvcfgh` does not exist when - XLEN=64. - - priv_mode: S - length: 64 - definedBy: - allOf: - - name: Sm - version: ">=1.12" - - name: H - fields: - STCE: - location: 63 - description: | - *STimecmp Enable* - - When set, `stimecmp` is operational in VS-mode if `menvcfg.STCE` is also set. - - When `menvcfg.STCE` is zero: - * `henvcfg.STCE` reads-as-zero - * `vstimecmp` access raises an `IllegalInstruction` exception. - * `hip.VSTIP` reverts to its defined behavior as if Sstc is not implemented. - * VS-mode timer interrupts will not be generated - - When `menvcfg.STCE` is one and `henvcfg.STCE` is zero: - * Accessing `stimecmp` in VS-mode or VU-mode (really `vstimecmp`) raises a VirtualInterrupt exception - * `hip.VSTIP` reverts to its defined behavior as if Sstc is not implemented. - * VS-mode timer interrupts will not be generated - - definedBy: Sstc - type(): | - return (implemented?(ExtensionName::Sstc)) ? CsrFieldType::RO : CsrFieldType::RW; - reset_value(): | - return (implemented?(ExtensionName::Sstc)) ? UNDEFINED_LEGAL : 0; - PBMTE: - location: 62 - description: | - *Page Based Memory Type Enable* - - The PBMTE bit controls whether the `Svpbmt` extension is available for use in VS-stage - address translation. - - When PBMTE=1, Svpbmt is available for VS-stage address translation. - - When PBMTE=0, the implementation behaves as though `Svpbmt` were not implemented for - VS-stage address translation. - - If `Svpbmt` is not implemented, PBMTE is read-only zero. - - `henvcfg.PBMTE` is read-as-zero if `menvcfg.PBMTE` is zero. - - If the setting of the PBMTE bit in `menvcfg` is changed, an `hfence.gvma` instruction with - _rs1_=_x0_ and _rs2_=_x0_ suffices to synchronize with respect to the altered interpretation - of G-stage and VS-stage PTEs' PBMT fields. - - By contrast, if the PBMTE bit in `henvcfg` is changed, executing an `hfence.vvma` with - _rs1_=_x0_ and _rs2_=_x0_ suffices to synchronize with respect to the altered interpretation - of VS-stage PTEs' PBMT fields for the currently active VMID. - - [NOTE] - -- - No mechanism is provided to atomically change `vsatp` and `hgatp` together. - Hence, to prevent speculative execution causing one guest's VS-stage translations to be - cached under another guest's VMID, world-switch code should zero `vsatp`, then swap `hgatp`, - then finally write the new `vsatp` value. - Similarly, if `henvcfg.PBMTE` need be world-switched, it should be switched after zeroing - `vsatp` but before writing the new `vsatp` value, obviating the need to execute an - `hfence.vvma` instruction. - -- - definedBy: Svpbmt - type(): | - return (implemented?(ExtensionName::Svpbmt)) ? CsrFieldType::RO : CsrFieldType::RW; - reset_value(): | - return (implemented?(ExtensionName::Svpbmt)) ? UNDEFINED_LEGAL : 0; - ADUE: - location: 61 - description: | - If the `Svadu` extension is implemented, the ADUE bit controls whether hardware updating of - PTE A/D bits is enabled for VS-stage address translation. - - When ADUE=1, hardware updating of PTE A/D bits is enabled during VS-stage address - translation, and the implementation behaves as though the Svade extension were not - implemented for VS-mode address translation. - - When ADUE=0, the implementation behaves as though Svade were implemented for VS-stage - address translation. - - If Svadu is not implemented, ADUE is read-only zero. - - Furthermore, for implementations with the hypervisor extension, henvcfg.ADUE is read-only - zero if menvcfg.ADUE is zero. - definedBy: Svadu - type(): | - return (implemented?(ExtensionName::Svadu)) ? CsrFieldType::RO : CsrFieldType::RW; - reset_value(): | - return (implemented?(ExtensionName::Svadu)) ? UNDEFINED_LEGAL : 0; - CBZE: - location: 7 - description: | - *Cache Block Zero instruction Enable* - - Enables the execution of the cache block zero instruction, `CBO.ZERO`, - <% if ext?(:S) %> - in S-mode - <% elsif ext?(:U) %> - in U-mode - <% end %>. - - * `0`: The instruction raises an illegal instruction or virtual instruction exception - * `1`: The instruction is executed - - definedBy: Zicboz - type: RW - reset_value: UNDEFINED_LEGAL - CBCFE: - location: 6 - description: | - *Cache Block Clean and Flush instruction Enable* - - Enables the execution of the cache block clean instruction, `CBO.CLEAN`, and the - cache block flush instruction, `CBO.FLUSH`, - <% if ext?(:S) %> - in S-mode - <% elsif ext?(:U) %> - in U-mode - <% end %>. - - * `0`: The instruction raises an illegal instruction or virtual instruction exception - * `1`: The instruction is executed - - definedBy: Zicbom - type: RW - reset_value: UNDEFINED_LEGAL - CBIE: - location: 5-4 - description: | - *Cache Block Invalidate instruction Enable* - - Enables the execution of the cache block invalidate instruction, `CBO.INVAL`, - <% if ext?(:S) %> - in S-mode - <% elsif ext?(:U) %> - in U-mode - <% end %>. - - * `00`: The instruction raises an illegal instruction or virtual instruction exception - * `01`: The instruction is executed and performs a flush operation - * `10`: _Reserved_ - * `11`: The instruction is executed and performs an invalidate operation - definedBy: Zicbom - type: RW-R - sw_write(csr_value): | - if (csr_value.CBIE == 0 || csr_value.CBIE == 1 || csr_value.CBIE == 3) { - return csr_value.CBIE; - } else { - return CSR[menvcfg].CBIE; - } - reset_value: UNDEFINED_LEGAL - FIOM: - location: 0 - description: | - *Fence of I/O implies Memory* - - When `menvcfg.FIOM` is set, - FENCE instructions ordering I/O regions also implicitly order memory regions when executed - in any mode less privileged than M-mode. - - [separator="!",%autowidth,float="center",align="center",cols="^,<",options="header"] - !=== - !Instruction bit !Meaning when set - !PI + - PO - !Predecessor device input and memory reads (PR implied) + - Predecessor device output and memory writes (PW implied) - !SI + - SO - !Successor device input and memory reads (SR implied) + - Successor device output and memory writes (SW implied) - !=== - - Similarly, for modes less privileged than M when FIOM=1, if an atomic - instruction that accesses a region ordered as device I/O has its _aq_ - and/or _rl_ bit set, then that instruction is ordered as though it - accesses both device I/O and memory. - - type: RW - reset_value: UNDEFINED_LEGAL - sw_read(): | - Bits<64> value = $bits(CSR[henvcfg]); - if (implemented?(ExtensionName::Sstc) && CSR[menvcfg].STCE == 0) { - # henvcfg.STCE must read-as-zero - value = value & ~(1 << 63); - } - if (implemented?(ExtensionName::Svpbmt) && CSR[menvcfg].PBMTE == 0) { - # henvcfg.PBMTE must read-as-zero - value = value & ~(1 << 62); - } - if (implemented?(ExtensionName::Svadu) && CSR[menvcfg].ADUE == 0) { - # henvcfg.ADUE must read-as-zero - value = value & ~(1 << 61); - } - return value; \ No newline at end of file +$schema: "csr_schema.json#" +kind: csr +name: henvcfg +address: 0x60A +long_name: Hypervisor Environment Configuration +description: | + The henvcfg CSR is a 64-bit read/write register that controls certain characteristics of the + execution environment when virtualization mode V=1. + + If bit `henvcfg.FIOM` (Fence of I/O implies Memory) is set to one in henvcfg, `fence` + instructions executed when V=1 are modified so the requirement to order accesses to device I/O + implies also the requirement to order main memory accesses. + + <> details the modified interpretation of FENCE instruction bits PI, PO, SI, and SO when + FIOM=1 and V=1. + + Similarly, when `henvcfg.FIOM`=1 and V=1, if an atomic instruction that accesses a + region ordered as device I/O has its _aq_ and/or _rl_ bit set, then that + instruction is ordered as though it accesses both device I/O and memory. + + [[henvcfg-FIOM]] + .Modified interpretation of FENCE predecessor and successor sets when FIOM=1 and virtualization mode V=1. + [%autowidth,float="center",align="center",cols="^,<",options="header"] + |=== + |Instruction bit |Meaning when set + |PI + + PO + |Predecessor device input and memory reads (PR implied) + + Predecessor device output and memory writes (PW implied) + |SI + + SO + |Successor device input and memory reads (SR implied) + + Successor device output and memory writes (SW implied) + |=== + + The PBMTE bit controls whether the Svpbmt extension is available for use + in VS-stage address translation. When PBMTE=1, Svpbmt is available for + VS-stage address translation. When PBMTE=0, the implementation behaves + as though Svpbmt were not implemented for VS-stage address translation. + If Svpbmt is not implemented, PBMTE is read-only zero. + + If the Svadu extension is implemented, the ADUE bit controls whether hardware + updating of PTE A/D bits is enabled for VS-stage address translation. + When ADUE=1, hardware updating of PTE A/D bits is enabled during VS-stage + address translation, and the implementation behaves as though the Svade + extension were not implemented for VS-mode address translation. + When ADUE=0, the implementation behaves as though Svade were implemented for + VS-stage address translation. + If Svadu is not implemented, ADUE is read-only zero. + + The definition of the STCE field is furnished by the Sstc extension. + + The definition of the CBZE field is furnished by the Zicboz extension. + + The definitions of the CBCFE and CBIE fields are furnished by the Zicbom extension. + + The definition of the PMM field will be furnished by the forthcoming + Ssnpm extension. Its allocation within `henvcfg` may change prior to the + ratification of that extension. + + The Zicfilp extension adds the `LPE` field in `henvcfg`. When the `LPE` field + is set to 1, the Zicfilp extension is enabled in VS-mode. When the `LPE` field + is 0, the Zicfilp extension is not enabled in VS-mode and the following rules + apply to VS-mode: + + * The hart does not update the `ELP` state; it remains as `NO_LP_EXPECTED`. + * The `LPAD` instruction operates as a no-op. + + The Zicfiss extension adds the `SSE` field in `henvcfg`. If the `SSE` field is + set to 1, the Zicfiss extension is activated in VS-mode. When the `SSE` field is + 0, the Zicfiss extension remains inactive in VS-mode, and the following rules + apply when `V=1`: + + * 32-bit Zicfiss instructions will revert to their behavior as defined by Zimop. + * 16-bit Zicfiss instructions will revert to their behavior as defined by Zcmop. + * The `pte.xwr=010b` encoding in VS-stage page tables becomes reserved. + * The `senvcfg.SSE` field will read as zero and is read-only. + * When `menvcfg.SSE` is one, `SSAMOSWAP.W/D` raises a virtual instruction + exception. + + The Ssdbltrp extension adds the double-trap-enable (`DTE`) field in `henvcfg`. + When `henvcfg.DTE` is zero, the implementation behaves as though Ssdbltrp is not + implemented for VS-mode and the `vsstatus.SDT` bit is read-only zero. + + When XLEN=32, `henvcfgh` is a + 32-bit read/write register that aliases bits 63:32 + of `henvcfg`. Register `henvcfgh` does not exist when + XLEN=64. + +priv_mode: S +length: 64 +definedBy: + allOf: + - name: Sm + version: ">=1.12" + - name: H +fields: + STCE: + location: 63 + description: | + *STimecmp Enable* + + When set, `stimecmp` is operational in VS-mode if `menvcfg.STCE` is also set. + + When `menvcfg.STCE` is zero: + * `henvcfg.STCE` reads-as-zero + * `vstimecmp` access raises an `IllegalInstruction` exception. + * `hip.VSTIP` reverts to its defined behavior as if Sstc is not implemented. + * VS-mode timer interrupts will not be generated + + When `menvcfg.STCE` is one and `henvcfg.STCE` is zero: + * Accessing `stimecmp` in VS-mode or VU-mode (really `vstimecmp`) raises a VirtualInterrupt exception + * `hip.VSTIP` reverts to its defined behavior as if Sstc is not implemented. + * VS-mode timer interrupts will not be generated + + definedBy: Sstc + type(): | + return (implemented?(ExtensionName::Sstc)) ? CsrFieldType::RO : CsrFieldType::RW; + reset_value(): | + return (implemented?(ExtensionName::Sstc)) ? UNDEFINED_LEGAL : 0; + PBMTE: + location: 62 + description: | + *Page Based Memory Type Enable* + + The PBMTE bit controls whether the `Svpbmt` extension is available for use in VS-stage + address translation. + + When PBMTE=1, Svpbmt is available for VS-stage address translation. + + When PBMTE=0, the implementation behaves as though `Svpbmt` were not implemented for + VS-stage address translation. + + If `Svpbmt` is not implemented, PBMTE is read-only zero. + + `henvcfg.PBMTE` is read-as-zero if `menvcfg.PBMTE` is zero. + + If the setting of the PBMTE bit in `menvcfg` is changed, an `hfence.gvma` instruction with + _rs1_=_x0_ and _rs2_=_x0_ suffices to synchronize with respect to the altered interpretation + of G-stage and VS-stage PTEs' PBMT fields. + + By contrast, if the PBMTE bit in `henvcfg` is changed, executing an `hfence.vvma` with + _rs1_=_x0_ and _rs2_=_x0_ suffices to synchronize with respect to the altered interpretation + of VS-stage PTEs' PBMT fields for the currently active VMID. + + [NOTE] + -- + No mechanism is provided to atomically change `vsatp` and `hgatp` together. + Hence, to prevent speculative execution causing one guest's VS-stage translations to be + cached under another guest's VMID, world-switch code should zero `vsatp`, then swap `hgatp`, + then finally write the new `vsatp` value. + Similarly, if `henvcfg.PBMTE` need be world-switched, it should be switched after zeroing + `vsatp` but before writing the new `vsatp` value, obviating the need to execute an + `hfence.vvma` instruction. + -- + definedBy: Svpbmt + type(): | + return (implemented?(ExtensionName::Svpbmt)) ? CsrFieldType::RO : CsrFieldType::RW; + reset_value(): | + return (implemented?(ExtensionName::Svpbmt)) ? UNDEFINED_LEGAL : 0; + ADUE: + location: 61 + description: | + If the `Svadu` extension is implemented, the ADUE bit controls whether hardware updating of + PTE A/D bits is enabled for VS-stage address translation. + + When ADUE=1, hardware updating of PTE A/D bits is enabled during VS-stage address + translation, and the implementation behaves as though the Svade extension were not + implemented for VS-mode address translation. + + When ADUE=0, the implementation behaves as though Svade were implemented for VS-stage + address translation. + + If Svadu is not implemented, ADUE is read-only zero. + + Furthermore, for implementations with the hypervisor extension, henvcfg.ADUE is read-only + zero if menvcfg.ADUE is zero. + definedBy: Svadu + type(): | + return (implemented?(ExtensionName::Svadu)) ? CsrFieldType::RO : CsrFieldType::RW; + reset_value(): | + return (implemented?(ExtensionName::Svadu)) ? UNDEFINED_LEGAL : 0; + CBZE: + location: 7 + description: | + *Cache Block Zero instruction Enable* + + Enables the execution of the cache block zero instruction, `CBO.ZERO`, + <% if ext?(:S) %> + in S-mode + <% elsif ext?(:U) %> + in U-mode + <% end %>. + + * `0`: The instruction raises an illegal instruction or virtual instruction exception + * `1`: The instruction is executed + + definedBy: Zicboz + type: RW + reset_value: UNDEFINED_LEGAL + CBCFE: + location: 6 + description: | + *Cache Block Clean and Flush instruction Enable* + + Enables the execution of the cache block clean instruction, `CBO.CLEAN`, and the + cache block flush instruction, `CBO.FLUSH`, + <% if ext?(:S) %> + in S-mode + <% elsif ext?(:U) %> + in U-mode + <% end %>. + + * `0`: The instruction raises an illegal instruction or virtual instruction exception + * `1`: The instruction is executed + + definedBy: Zicbom + type: RW + reset_value: UNDEFINED_LEGAL + CBIE: + location: 5-4 + description: | + *Cache Block Invalidate instruction Enable* + + Enables the execution of the cache block invalidate instruction, `CBO.INVAL`, + <% if ext?(:S) %> + in S-mode + <% elsif ext?(:U) %> + in U-mode + <% end %>. + + * `00`: The instruction raises an illegal instruction or virtual instruction exception + * `01`: The instruction is executed and performs a flush operation + * `10`: _Reserved_ + * `11`: The instruction is executed and performs an invalidate operation + definedBy: Zicbom + type: RW-R + sw_write(csr_value): | + if (csr_value.CBIE == 0 || csr_value.CBIE == 1 || csr_value.CBIE == 3) { + return csr_value.CBIE; + } else { + return CSR[menvcfg].CBIE; + } + reset_value: UNDEFINED_LEGAL + FIOM: + location: 0 + description: | + *Fence of I/O implies Memory* + + When `menvcfg.FIOM` is set, + FENCE instructions ordering I/O regions also implicitly order memory regions when executed + in any mode less privileged than M-mode. + + [separator="!",%autowidth,float="center",align="center",cols="^,<",options="header"] + !=== + !Instruction bit !Meaning when set + !PI + + PO + !Predecessor device input and memory reads (PR implied) + + Predecessor device output and memory writes (PW implied) + !SI + + SO + !Successor device input and memory reads (SR implied) + + Successor device output and memory writes (SW implied) + !=== + + Similarly, for modes less privileged than M when FIOM=1, if an atomic + instruction that accesses a region ordered as device I/O has its _aq_ + and/or _rl_ bit set, then that instruction is ordered as though it + accesses both device I/O and memory. + + type: RW + reset_value: UNDEFINED_LEGAL +sw_read(): | + Bits<64> value = $bits(CSR[henvcfg]); + if (implemented?(ExtensionName::Sstc) && CSR[menvcfg].STCE == 0) { + # henvcfg.STCE must read-as-zero + value = value & ~(1 << 63); + } + if (implemented?(ExtensionName::Svpbmt) && CSR[menvcfg].PBMTE == 0) { + # henvcfg.PBMTE must read-as-zero + value = value & ~(1 << 62); + } + if (implemented?(ExtensionName::Svadu) && CSR[menvcfg].ADUE == 0) { + # henvcfg.ADUE must read-as-zero + value = value & ~(1 << 61); + } + return value; \ No newline at end of file diff --git a/arch/csr/H/henvcfgh.yaml b/arch/csr/H/henvcfgh.yaml index 420e825f6..692e159fe 100644 --- a/arch/csr/H/henvcfgh.yaml +++ b/arch/csr/H/henvcfgh.yaml @@ -1,105 +1,107 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -henvcfgh: - address: 0x61A - long_name: most-significant 32 bits of Hypervisor Environment Configuration - description: | - The henvcfgh CSR is a 32-bit read/write register for the most-significant 32 bits of `henvcfg`. - priv_mode: S - length: 32 - definedBy: - allOf: - - name: Sm - version: ">=1.12" - - name: H - fields: - STCE: - location: 31 - alias: henvcfg.STCE - description: | - *STimecmp Enable* +$schema: "csr_schema.json#" +kind: csr +name: henvcfgh +address: 0x61A +long_name: most-significant 32 bits of Hypervisor Environment Configuration +description: | + The henvcfgh CSR is a 32-bit read/write register for the most-significant 32 bits of `henvcfg`. +priv_mode: S +length: 32 +definedBy: + allOf: + - name: Sm + version: ">=1.12" + - name: H +fields: + STCE: + location: 31 + alias: henvcfg.STCE + description: | + *STimecmp Enable* - When set, `stimecmp` is operational in VS-mode if `menvcfg.STCE` is also set. + When set, `stimecmp` is operational in VS-mode if `menvcfg.STCE` is also set. - When `menvcfg.STCE` is zero: - * `henvcfg.STCE` reads-as-zero - * `vstimecmp` access raises an `IllegalInstruction` exception. - * `hip.VSTIP` reverts to its defined behavior as if Sstc is not implemented. - * VS-mode timer interrupts will not be generated + When `menvcfg.STCE` is zero: + * `henvcfg.STCE` reads-as-zero + * `vstimecmp` access raises an `IllegalInstruction` exception. + * `hip.VSTIP` reverts to its defined behavior as if Sstc is not implemented. + * VS-mode timer interrupts will not be generated - When `menvcfg.STCE` is one and `henvcfg.STCE` is zero: - * Accessing `stimecmp` in VS-mode or VU-mode (really `vstimecmp`) raises a VirtualInterrupt exception - * `hip.VSTIP` reverts to its defined behavior as if Sstc is not implemented. - * VS-mode timer interrupts will not be generated + When `menvcfg.STCE` is one and `henvcfg.STCE` is zero: + * Accessing `stimecmp` in VS-mode or VU-mode (really `vstimecmp`) raises a VirtualInterrupt exception + * `hip.VSTIP` reverts to its defined behavior as if Sstc is not implemented. + * VS-mode timer interrupts will not be generated - definedBy: Sstc - type(): | - return (implemented?(ExtensionName::Sstc)) ? CsrFieldType::RO : CsrFieldType::RW; - reset_value(): | - return (implemented?(ExtensionName::Sstc)) ? UNDEFINED_LEGAL : 0; - PBMTE: - location: 30 - alias: henvcfg.PBMTE - description: | - *Page Based Memory Type Enable* + definedBy: Sstc + type(): | + return (implemented?(ExtensionName::Sstc)) ? CsrFieldType::RO : CsrFieldType::RW; + reset_value(): | + return (implemented?(ExtensionName::Sstc)) ? UNDEFINED_LEGAL : 0; + PBMTE: + location: 30 + alias: henvcfg.PBMTE + description: | + *Page Based Memory Type Enable* - The PBMTE bit controls whether the `Svpbmt` extension is available for use in VS-stage - address translation. - - When PBMTE=1, Svpbmt is available for VS-stage address translation. - - When PBMTE=0, the implementation behaves as though `Svpbmt` were not implemented for - VS-stage address translation. - - If `Svpbmt` is not implemented, PBMTE is read-only zero. + The PBMTE bit controls whether the `Svpbmt` extension is available for use in VS-stage + address translation. + + When PBMTE=1, Svpbmt is available for VS-stage address translation. + + When PBMTE=0, the implementation behaves as though `Svpbmt` were not implemented for + VS-stage address translation. + + If `Svpbmt` is not implemented, PBMTE is read-only zero. - `henvcfg.PBMTE` is read-as-zero if `menvcfg.PBMTE` is zero. + `henvcfg.PBMTE` is read-as-zero if `menvcfg.PBMTE` is zero. - If the setting of the PBMTE bit in `menvcfg` is changed, an `hfence.gvma` instruction with - _rs1_=_x0_ and _rs2_=_x0_ suffices to synchronize with respect to the altered interpretation - of G-stage and VS-stage PTEs' PBMT fields. + If the setting of the PBMTE bit in `menvcfg` is changed, an `hfence.gvma` instruction with + _rs1_=_x0_ and _rs2_=_x0_ suffices to synchronize with respect to the altered interpretation + of G-stage and VS-stage PTEs' PBMT fields. - By contrast, if the PBMTE bit in `henvcfg` is changed, executing an `hfence.vvma` with - _rs1_=_x0_ and _rs2_=_x0_ suffices to synchronize with respect to the altered interpretation - of VS-stage PTEs' PBMT fields for the currently active VMID. + By contrast, if the PBMTE bit in `henvcfg` is changed, executing an `hfence.vvma` with + _rs1_=_x0_ and _rs2_=_x0_ suffices to synchronize with respect to the altered interpretation + of VS-stage PTEs' PBMT fields for the currently active VMID. - [NOTE] - -- - No mechanism is provided to atomically change `vsatp` and `hgatp` together. - Hence, to prevent speculative execution causing one guest's VS-stage translations to be - cached under another guest's VMID, world-switch code should zero `vsatp`, then swap `hgatp`, - then finally write the new `vsatp` value. - Similarly, if `henvcfg.PBMTE` need be world-switched, it should be switched after zeroing - `vsatp` but before writing the new `vsatp` value, obviating the need to execute an - `hfence.vvma` instruction. - -- - definedBy: Svpbmt - type(): | - return (implemented?(ExtensionName::Svpbmt)) ? CsrFieldType::RO : CsrFieldType::RW; - reset_value(): | - return (implemented?(ExtensionName::Svpbmt)) ? UNDEFINED_LEGAL : 0; - ADUE: - location: 29 - alias: henvcfg.ADUE - description: | - If the `Svadu` extension is implemented, the ADUE bit controls whether hardware updating of - PTE A/D bits is enabled for VS-stage address translation. - - When ADUE=1, hardware updating of PTE A/D bits is enabled during VS-stage address - translation, and the implementation behaves as though the Svade extension were not - implemented for VS-mode address translation. - - When ADUE=0, the implementation behaves as though Svade were implemented for VS-stage - address translation. - - If Svadu is not implemented, ADUE is read-only zero. + [NOTE] + -- + No mechanism is provided to atomically change `vsatp` and `hgatp` together. + Hence, to prevent speculative execution causing one guest's VS-stage translations to be + cached under another guest's VMID, world-switch code should zero `vsatp`, then swap `hgatp`, + then finally write the new `vsatp` value. + Similarly, if `henvcfg.PBMTE` need be world-switched, it should be switched after zeroing + `vsatp` but before writing the new `vsatp` value, obviating the need to execute an + `hfence.vvma` instruction. + -- + definedBy: Svpbmt + type(): | + return (implemented?(ExtensionName::Svpbmt)) ? CsrFieldType::RO : CsrFieldType::RW; + reset_value(): | + return (implemented?(ExtensionName::Svpbmt)) ? UNDEFINED_LEGAL : 0; + ADUE: + location: 29 + alias: henvcfg.ADUE + description: | + If the `Svadu` extension is implemented, the ADUE bit controls whether hardware updating of + PTE A/D bits is enabled for VS-stage address translation. + + When ADUE=1, hardware updating of PTE A/D bits is enabled during VS-stage address + translation, and the implementation behaves as though the Svade extension were not + implemented for VS-mode address translation. + + When ADUE=0, the implementation behaves as though Svade were implemented for VS-stage + address translation. + + If Svadu is not implemented, ADUE is read-only zero. - Furthermore, for implementations with the hypervisor extension, henvcfg.ADUE is read-only - zero if menvcfg.ADUE is zero. - definedBy: Svadu - type(): | - return (implemented?(ExtensionName::Svadu)) ? CsrFieldType::RO : CsrFieldType::RW; - reset_value(): | - return (implemented?(ExtensionName::Svadu)) ? UNDEFINED_LEGAL : 0; - sw_read(): | - return CSR[henvcfg].sw_read()[63:32]; \ No newline at end of file + Furthermore, for implementations with the hypervisor extension, henvcfg.ADUE is read-only + zero if menvcfg.ADUE is zero. + definedBy: Svadu + type(): | + return (implemented?(ExtensionName::Svadu)) ? CsrFieldType::RO : CsrFieldType::RW; + reset_value(): | + return (implemented?(ExtensionName::Svadu)) ? UNDEFINED_LEGAL : 0; +sw_read(): | + return CSR[henvcfg].sw_read()[63:32]; \ No newline at end of file diff --git a/arch/csr/H/hgatp.yaml b/arch/csr/H/hgatp.yaml index 0ef027e12..01bb120e1 100644 --- a/arch/csr/H/hgatp.yaml +++ b/arch/csr/H/hgatp.yaml @@ -1,234 +1,236 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -hgatp: - long_name: Hypervisor guest address translation and protection - description: | - The hgatp register is an HSXLEN-bit read/write register - which controls G-stage address translation and protection, the second stage of two-stage - translation for guest virtual addresses. - Similar to CSR `satp`, this register holds the physical page number (PPN) of the - guest-physical root page table; - a virtual machine identifier (VMID), which facilitates address-translation fences on a - per-virtual-machine basis; - and the MODE field, which selects the address-translation scheme for guest physical addresses. - When `mstatus.TVM`=1, attempts to read or write `hgatp` while executing in HS-mode will - raise an `IllegalInstruction` exception. - - <> shows the encodings of the MODE field when - HSXLEN=32 and HSXLEN=64. When MODE=Bare, guest physical addresses are - equal to supervisor physical addresses, and there is no further memory - protection for a guest virtual machine beyond the physical memory - protection scheme described in <>. In this - case, the remaining fields in `hgatp` must be set to zeros. - - [[hgatp-mode]] - .Encoding of `hgatp` MODE field. - [%autowidth,float="center",align="center",cols="^,^,<",options="header"] - |=== - 3+|HSXLEN=32 - |Value |Name |Description - |0 + - 1 - |Bare + - Sv32x4 - |No translation or protection. + - Page-based 34-bit virtual addressing (2-bit extension of - Sv32). - 3+s|HSXLEN=64 - |Value |Name |Description - |0 + - 1-7 + - 8 + - 9 + - 10 + - 11-15 - |Bare + - -- + - Sv39x4 + - Sv48x4 + - Sv57x4 + - -- - |No translation or protection. + - _Reserved_ + - Page-based 41-bit virtual addressing (2-bit extension of - Sv39). + - Page-based 50-bit virtual addressing (2-bit extension of - Sv48). + - Page-based 59-bit virtual addressing (2-bit extension of - Sv57). + - _Reserved_ - |=== - - Implementations are not required to support all defined MODE settings - when HSXLEN=64. - - A write to `hgatp` with an unsupported MODE value is not ignored as it - is for `satp`. Instead, the fields of `hgatp` are *WARL* in the normal way, - when so indicated. - - As explained in <>, for the - paged virtual-memory schemes (Sv32x4, Sv39x4, Sv48x4, and Sv57x4), the - root page table is 16 KiB and must be aligned to a 16-KiB boundary. In - these modes, the lowest two bits of the physical page number (PPN) in - `hgatp` always read as zeros. An implementation that supports only the - defined paged virtual-memory schemes and/or Bare may make PPN[1:0] - read-only zero. - - The number of VMID bits is UNSPECIFIED and may be zero. The number of implemented - VMID bits, termed _VMIDLEN_, may be determined by writing one to every - bit position in the VMID field, then reading back the value in `hgatp` - to see which bit positions in the VMID field hold a one. The - least-significant bits of VMID are implemented first: that is, if - VMIDLEN > 0, VMID[VMIDLEN-1:0] is writable. The maximal - value of VMIDLEN, termed VMIDMAX, is 7 for Sv32x4 or 14 for Sv39x4, - Sv48x4, and Sv57x4. - - The `hgatp` register is considered _active_ for the purposes of the - address-translation algorithm _unless_ the effective privilege mode is U - and `hstatus`.HU=0. - - [NOTE] - ==== - This definition simplifies the implementation of speculative execution - of `hlv`, `hlvx`, and 'hsv' instructions. - ==== - - Note that writing `hgatp` does not imply any ordering constraints - between page-table updates and subsequent G-stage address translations. - If the new virtual machine's guest physical page tables have been - modified, or if a VMID is reused, it may be necessary to execute an - HFENCE.GVMA instruction (see <>) before or - after writing `hgatp`. - address: 0x680 - priv_mode: S - definedBy: H - length: SXLEN - fields: - MODE: - location_rv32: 31 - location_rv64: 63-60 - description: | - When MODE=Bare, guest physical addresses are equal to supervisor physical addresses, - and there is no further memory protection for a guest virtual machine beyond the - physical memory protection scheme. - In this case, the remaining fields in hgatp must be set to zeros. - - When HSXLEN=32, the only other valid setting for MODE is Sv32x4, which is a - modification of the usual Sv32 paged virtual-memory scheme, extended to support - 34-bit guest physical addresses. - When HSXLEN=64, modes Sv39x4, Sv48x4, and Sv57x4 are defined as modifications of the - Sv39, Sv48, and Sv57 paged virtual-memory schemes. - - A write to hgatp with an unsupported MODE value is not ignored as it is for `satp`. - Instead, the fields of hgatp are WARL in the normal way, when so indicated. - type: RW - reset_value: UNDEFINED_LEGAL - sw_write(csr_value): | - if (csr_value.MODE == $bits(HgatpMode::Bare)) { - if (!GSTAGE_MODE_BARE) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } - } - - if (csr_value.MODE == $bits(HgatpMode::Sv32x4)) { - if (!SV32X4_TRANSLATION) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } +$schema: "csr_schema.json#" +kind: csr +name: hgatp +long_name: Hypervisor guest address translation and protection +description: | + The hgatp register is an HSXLEN-bit read/write register + which controls G-stage address translation and protection, the second stage of two-stage + translation for guest virtual addresses. + Similar to CSR `satp`, this register holds the physical page number (PPN) of the + guest-physical root page table; + a virtual machine identifier (VMID), which facilitates address-translation fences on a + per-virtual-machine basis; + and the MODE field, which selects the address-translation scheme for guest physical addresses. + When `mstatus.TVM`=1, attempts to read or write `hgatp` while executing in HS-mode will + raise an `IllegalInstruction` exception. + + <> shows the encodings of the MODE field when + HSXLEN=32 and HSXLEN=64. When MODE=Bare, guest physical addresses are + equal to supervisor physical addresses, and there is no further memory + protection for a guest virtual machine beyond the physical memory + protection scheme described in <>. In this + case, the remaining fields in `hgatp` must be set to zeros. + + [[hgatp-mode]] + .Encoding of `hgatp` MODE field. + [%autowidth,float="center",align="center",cols="^,^,<",options="header"] + |=== + 3+|HSXLEN=32 + |Value |Name |Description + |0 + + 1 + |Bare + + Sv32x4 + |No translation or protection. + + Page-based 34-bit virtual addressing (2-bit extension of + Sv32). + 3+s|HSXLEN=64 + |Value |Name |Description + |0 + + 1-7 + + 8 + + 9 + + 10 + + 11-15 + |Bare + + -- + + Sv39x4 + + Sv48x4 + + Sv57x4 + + -- + |No translation or protection. + + _Reserved_ + + Page-based 41-bit virtual addressing (2-bit extension of + Sv39). + + Page-based 50-bit virtual addressing (2-bit extension of + Sv48). + + Page-based 59-bit virtual addressing (2-bit extension of + Sv57). + + _Reserved_ + |=== + + Implementations are not required to support all defined MODE settings + when HSXLEN=64. + + A write to `hgatp` with an unsupported MODE value is not ignored as it + is for `satp`. Instead, the fields of `hgatp` are *WARL* in the normal way, + when so indicated. + + As explained in <>, for the + paged virtual-memory schemes (Sv32x4, Sv39x4, Sv48x4, and Sv57x4), the + root page table is 16 KiB and must be aligned to a 16-KiB boundary. In + these modes, the lowest two bits of the physical page number (PPN) in + `hgatp` always read as zeros. An implementation that supports only the + defined paged virtual-memory schemes and/or Bare may make PPN[1:0] + read-only zero. + + The number of VMID bits is UNSPECIFIED and may be zero. The number of implemented + VMID bits, termed _VMIDLEN_, may be determined by writing one to every + bit position in the VMID field, then reading back the value in `hgatp` + to see which bit positions in the VMID field hold a one. The + least-significant bits of VMID are implemented first: that is, if + VMIDLEN > 0, VMID[VMIDLEN-1:0] is writable. The maximal + value of VMIDLEN, termed VMIDMAX, is 7 for Sv32x4 or 14 for Sv39x4, + Sv48x4, and Sv57x4. + + The `hgatp` register is considered _active_ for the purposes of the + address-translation algorithm _unless_ the effective privilege mode is U + and `hstatus`.HU=0. + + [NOTE] + ==== + This definition simplifies the implementation of speculative execution + of `hlv`, `hlvx`, and 'hsv' instructions. + ==== + + Note that writing `hgatp` does not imply any ordering constraints + between page-table updates and subsequent G-stage address translations. + If the new virtual machine's guest physical page tables have been + modified, or if a VMID is reused, it may be necessary to execute an + HFENCE.GVMA instruction (see <>) before or + after writing `hgatp`. +address: 0x680 +priv_mode: S +definedBy: H +length: SXLEN +fields: + MODE: + location_rv32: 31 + location_rv64: 63-60 + description: | + When MODE=Bare, guest physical addresses are equal to supervisor physical addresses, + and there is no further memory protection for a guest virtual machine beyond the + physical memory protection scheme. + In this case, the remaining fields in hgatp must be set to zeros. + + When HSXLEN=32, the only other valid setting for MODE is Sv32x4, which is a + modification of the usual Sv32 paged virtual-memory scheme, extended to support + 34-bit guest physical addresses. + When HSXLEN=64, modes Sv39x4, Sv48x4, and Sv57x4 are defined as modifications of the + Sv39, Sv48, and Sv57 paged virtual-memory schemes. + + A write to hgatp with an unsupported MODE value is not ignored as it is for `satp`. + Instead, the fields of hgatp are WARL in the normal way, when so indicated. + type: RW + reset_value: UNDEFINED_LEGAL + sw_write(csr_value): | + if (csr_value.MODE == $bits(HgatpMode::Bare)) { + if (!GSTAGE_MODE_BARE) { + return UNDEFINED_LEGAL_DETERMINISTIC; } + } - if (csr_value.MODE == $bits(HgatpMode::Sv39x4)) { - if (!SV39X4_TRANSLATION) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + if (csr_value.MODE == $bits(HgatpMode::Sv32x4)) { + if (!SV32X4_TRANSLATION) { + return UNDEFINED_LEGAL_DETERMINISTIC; } + } - if (csr_value.MODE == $bits(HgatpMode::Sv48x4)) { - if (!SV48X4_TRANSLATION) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + if (csr_value.MODE == $bits(HgatpMode::Sv39x4)) { + if (!SV39X4_TRANSLATION) { + return UNDEFINED_LEGAL_DETERMINISTIC; } + } - if (csr_value.MODE == $bits(HgatpMode::Sv57x4)) { - if (!SV57X4_TRANSLATION) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + if (csr_value.MODE == $bits(HgatpMode::Sv48x4)) { + if (!SV48X4_TRANSLATION) { + return UNDEFINED_LEGAL_DETERMINISTIC; } + } - # mode is supported - return csr_value.MODE; - VMID: - location_rv32: 28-22 - location_rv64: 57-44 - description: | - Virtual machine ID. - - The number of VMID bits is determined by parameter VMID_WIDTH. - VMID_WIDTH may be determined by software by writing one to every bit position in - the VMID field, then reading back the value in hgatp to see which bit - positions in the VMID field hold a one. - The least-significant bits of VMID are implemented first: - that is, if VMID_WIDTH > 0, VMID[VMID_WIDTH-1:0] is writable. - The maximal value of VMID_WIDTH, termed VMIDMAX, is 7 for Sv32x4 or - 14 for Sv39x4, Sv48x4, and Sv57x4. - type(): | - if (VMID_WIDTH == 0) { - return CsrFieldType::RO; - } else { - return CsrFieldType::RW; + if (csr_value.MODE == $bits(HgatpMode::Sv57x4)) { + if (!SV57X4_TRANSLATION) { + return UNDEFINED_LEGAL_DETERMINISTIC; } - reset_value(): | - if (VMID_WIDTH == 0) { + } + + # mode is supported + return csr_value.MODE; + VMID: + location_rv32: 28-22 + location_rv64: 57-44 + description: | + Virtual machine ID. + + The number of VMID bits is determined by parameter VMID_WIDTH. + VMID_WIDTH may be determined by software by writing one to every bit position in + the VMID field, then reading back the value in hgatp to see which bit + positions in the VMID field hold a one. + The least-significant bits of VMID are implemented first: + that is, if VMID_WIDTH > 0, VMID[VMID_WIDTH-1:0] is writable. + The maximal value of VMID_WIDTH, termed VMIDMAX, is 7 for Sv32x4 or + 14 for Sv39x4, Sv48x4, and Sv57x4. + type(): | + if (VMID_WIDTH == 0) { + return CsrFieldType::RO; + } else { + return CsrFieldType::RW; + } + reset_value(): | + if (VMID_WIDTH == 0) { + return 0; + } else { + return UNDEFINED_LEGAL; + } + sw_write(csr_value): | + if (csr_value.MODE == $bits(HgatpMode::Bare)) { + # when MODE == Bare, PPN and VMID must be 0 + if (csr_value.VMID == 0) { return 0; } else { - return UNDEFINED_LEGAL; - } - sw_write(csr_value): | - if (csr_value.MODE == $bits(HgatpMode::Bare)) { - # when MODE == Bare, PPN and VMID must be 0 - if (csr_value.VMID == 0) { - return 0; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } - } - return csr_value.VMID[VMID_WIDTH-1:0]; - PPN: - location_rv32: 21-0 - location_rv64: 43-0 - description: | - The physical page number (PPN) of the guest-physical root page table. - type(): | - if (!SV32X4_TRANSLATION && !SV39X4_TRANSLATION && !SV48X4_TRANSLATION && !SV57X4_TRANSLATION) { - # Bare is the only supported mode, PPN is always 0 - return CsrFieldType::RO; - } else { - return CsrFieldType::RW; + return UNDEFINED_LEGAL_DETERMINISTIC; } - reset_value(): | - if (!SV32X4_TRANSLATION && !SV39X4_TRANSLATION && !SV48X4_TRANSLATION && !SV57X4_TRANSLATION) { - # Bare is the only supported mode, PPN is always 0 + } + return csr_value.VMID[VMID_WIDTH-1:0]; + PPN: + location_rv32: 21-0 + location_rv64: 43-0 + description: | + The physical page number (PPN) of the guest-physical root page table. + type(): | + if (!SV32X4_TRANSLATION && !SV39X4_TRANSLATION && !SV48X4_TRANSLATION && !SV57X4_TRANSLATION) { + # Bare is the only supported mode, PPN is always 0 + return CsrFieldType::RO; + } else { + return CsrFieldType::RW; + } + reset_value(): | + if (!SV32X4_TRANSLATION && !SV39X4_TRANSLATION && !SV48X4_TRANSLATION && !SV57X4_TRANSLATION) { + # Bare is the only supported mode, PPN is always 0 + return 0; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } + sw_write(csr_value): | + if (csr_value.MODE == $bits(HgatpMode::Bare)) { + # when MODE == Bare, PPN and VMID must be 0 + if (csr_value.PPN == 0) { return 0; } else { return UNDEFINED_LEGAL_DETERMINISTIC; } - sw_write(csr_value): | - if (csr_value.MODE == $bits(HgatpMode::Bare)) { - # when MODE == Bare, PPN and VMID must be 0 - if (csr_value.PPN == 0) { - return 0; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } - } - return csr_value.PPN; - - sw_read(): | - if ((CSR[hgatp].MODE == $bits(HgatpMode::Sv32x4)) - || (CSR[hgatp].MODE == $bits(HgatpMode::Sv39x4)) - || (CSR[hgatp].MODE == $bits(HgatpMode::Sv48x4)) - || (CSR[hgatp].MODE == $bits(HgatpMode::Sv57x4))) { - # bits 1:0 of PPN read as zero - return $bits(CSR[hgatp]) & ~64'h3; - } else { - return $bits(CSR[hgatp]); - } \ No newline at end of file + } + return csr_value.PPN; + +sw_read(): | + if ((CSR[hgatp].MODE == $bits(HgatpMode::Sv32x4)) + || (CSR[hgatp].MODE == $bits(HgatpMode::Sv39x4)) + || (CSR[hgatp].MODE == $bits(HgatpMode::Sv48x4)) + || (CSR[hgatp].MODE == $bits(HgatpMode::Sv57x4))) { + # bits 1:0 of PPN read as zero + return $bits(CSR[hgatp]) & ~64'h3; + } else { + return $bits(CSR[hgatp]); + } \ No newline at end of file diff --git a/arch/csr/H/htimedelta.yaml b/arch/csr/H/htimedelta.yaml index 9f5f9f141..48de13f53 100644 --- a/arch/csr/H/htimedelta.yaml +++ b/arch/csr/H/htimedelta.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -htimedelta: - long_name: Hypervisor time delta - description: | - The `htimedelta` CSR is a 64-bit read/write register that contains the delta - between the value of the `time` CSR and the value returned in VS-mode or VU-mode. - That is, reading the `time` CSR in VS or VU mode returns the sum of the contents - of `htimedelta` and the actual value of `time`. +$schema: "csr_schema.json#" +kind: csr +name: htimedelta +long_name: Hypervisor time delta +description: | + The `htimedelta` CSR is a 64-bit read/write register that contains the delta + between the value of the `time` CSR and the value returned in VS-mode or VU-mode. + That is, reading the `time` CSR in VS or VU mode returns the sum of the contents + of `htimedelta` and the actual value of `time`. - [NOTE] - Because overflow is ignored when summing `htimedelta` and `time`, large values of - `htimedelta` may be used to represent negative time offsets. + [NOTE] + Because overflow is ignored when summing `htimedelta` and `time`, large values of + `htimedelta` may be used to represent negative time offsets. - address: 0x605 - priv_mode: S - definedBy: H - length: 64 - fields: - DELTA: - location: 63-0 - description: Signed delta - type: RW - reset_value: UNDEFINED_LEGAL +address: 0x605 +priv_mode: S +definedBy: H +length: 64 +fields: + DELTA: + location: 63-0 + description: Signed delta + type: RW + reset_value: UNDEFINED_LEGAL diff --git a/arch/csr/H/htimedeltah.yaml b/arch/csr/H/htimedeltah.yaml index 584893915..9aad2147e 100644 --- a/arch/csr/H/htimedeltah.yaml +++ b/arch/csr/H/htimedeltah.yaml @@ -1,22 +1,24 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -htimedeltah: - long_name: Hypervisor time delta, upper half - description: | - Upper half of the `htimedelta` CSR. +$schema: "csr_schema.json#" +kind: csr +name: htimedeltah +long_name: Hypervisor time delta, upper half +description: | + Upper half of the `htimedelta` CSR. - address: 0x615 - priv_mode: S - definedBy: H - length: 32 - fields: - DELTA: - location: 31-0 - description: Signed delta - type: RW - reset_value: UNDEFINED_LEGAL - sw_write(csr_value): | - CSR[htimedelta].DELTA = {csr_value.DELTA, CSR[htimedelta].DELTA[31:0]}; - return csr_value.DELTA; - sw_read(): | - return CSR[htimedelta].DELTA[31:0]; +address: 0x615 +priv_mode: S +definedBy: H +length: 32 +fields: + DELTA: + location: 31-0 + description: Signed delta + type: RW + reset_value: UNDEFINED_LEGAL + sw_write(csr_value): | + CSR[htimedelta].DELTA = {csr_value.DELTA, CSR[htimedelta].DELTA[31:0]}; + return csr_value.DELTA; +sw_read(): | + return CSR[htimedelta].DELTA[31:0]; diff --git a/arch/csr/H/htinst.yaml b/arch/csr/H/htinst.yaml index 1f8752aab..770bb92ec 100644 --- a/arch/csr/H/htinst.yaml +++ b/arch/csr/H/htinst.yaml @@ -1,42 +1,44 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -htinst: - address: 0x64a - long_name: Hypervisor Trap Instruction Register - description: | - When a trap is taken into HS-mode, mtinst is written with a value that, if nonzero, - provides information about the instruction that trapped, to assist software in handling the trap. - The values that may be written to mtinst on a trap are documented in TODO. +$schema: "csr_schema.json#" +kind: csr +name: htinst +address: 0x64a +long_name: Hypervisor Trap Instruction Register +description: | + When a trap is taken into HS-mode, mtinst is written with a value that, if nonzero, + provides information about the instruction that trapped, to assist software in handling the trap. + The values that may be written to mtinst on a trap are documented in TODO. - htinst is a WARL register that need only be able to hold the values that the implementation may automatically write to it on a trap. - priv_mode: S - length: SXLEN - definedBy: H - fields: - VALUE: - location_rv64: 63-0 - location_rv32: 31-0 - type(): | - if ( (TINST_VALUE_ON_FINAL_LOAD_GUEST_PAGE_FAULT != "always zero") - || (TINST_VALUE_ON_FINAL_STORE_AMO_GUEST_PAGE_FAULT != "always zero") - || (TINST_VALUE_ON_FINAL_INSTRUCTION_GUEST_PAGE_FAULT != "always zero") - || (TINST_VALUE_ON_INSTRUCTION_ADDRESS_MISALIGNED != "always zero") - || (TINST_VALUE_ON_BREAKPOINT != "always zero") - || (TINST_VALUE_ON_VIRTUAL_INSTRUCTION != "always zero") - || (TINST_VALUE_ON_LOAD_ADDRESS_MISALIGNED != "always zero") - || (TINST_VALUE_ON_LOAD_ACCESS_FAULT != "always zero") - || (TINST_VALUE_ON_STORE_AMO_ADDRESS_MISALIGNED != "always zero") - || (TINST_VALUE_ON_STORE_AMO_ACCESS_FAULT != "always_zero") - || (TINST_VALUE_ON_UCALL != "always zero") - || (TINST_VALUE_ON_SCALL != "always zero") - || (TINST_VALUE_ON_MCALL != "always zero") - || (TINST_VALUE_ON_VSCALL != "always zero") - || (TINST_VALUE_ON_LOAD_PAGE_FAULT != "always zero") - || (TINST_VALUE_ON_STORE_AMO_PAGE_FAULT != "always zero")) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - description: | - Exception-speicific information for a trap into HS-mode. - reset_value: UNDEFINED_LEGAL + htinst is a WARL register that need only be able to hold the values that the implementation may automatically write to it on a trap. +priv_mode: S +length: SXLEN +definedBy: H +fields: + VALUE: + location_rv64: 63-0 + location_rv32: 31-0 + type(): | + if ( (TINST_VALUE_ON_FINAL_LOAD_GUEST_PAGE_FAULT != "always zero") + || (TINST_VALUE_ON_FINAL_STORE_AMO_GUEST_PAGE_FAULT != "always zero") + || (TINST_VALUE_ON_FINAL_INSTRUCTION_GUEST_PAGE_FAULT != "always zero") + || (TINST_VALUE_ON_INSTRUCTION_ADDRESS_MISALIGNED != "always zero") + || (TINST_VALUE_ON_BREAKPOINT != "always zero") + || (TINST_VALUE_ON_VIRTUAL_INSTRUCTION != "always zero") + || (TINST_VALUE_ON_LOAD_ADDRESS_MISALIGNED != "always zero") + || (TINST_VALUE_ON_LOAD_ACCESS_FAULT != "always zero") + || (TINST_VALUE_ON_STORE_AMO_ADDRESS_MISALIGNED != "always zero") + || (TINST_VALUE_ON_STORE_AMO_ACCESS_FAULT != "always_zero") + || (TINST_VALUE_ON_UCALL != "always zero") + || (TINST_VALUE_ON_SCALL != "always zero") + || (TINST_VALUE_ON_MCALL != "always zero") + || (TINST_VALUE_ON_VSCALL != "always zero") + || (TINST_VALUE_ON_LOAD_PAGE_FAULT != "always zero") + || (TINST_VALUE_ON_STORE_AMO_PAGE_FAULT != "always zero")) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + description: | + Exception-speicific information for a trap into HS-mode. + reset_value: UNDEFINED_LEGAL diff --git a/arch/csr/H/htval.yaml b/arch/csr/H/htval.yaml index c2fcc250e..ab6082082 100644 --- a/arch/csr/H/htval.yaml +++ b/arch/csr/H/htval.yaml @@ -1,34 +1,36 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -htval: - address: 0x643 - long_name: Hypervisor Trap Value Register - description: | - When a trap is taken into HS-mode, htval is written with additional exception-specific information, alongside stval, to assist software in handling the trap. +$schema: "csr_schema.json#" +kind: csr +name: htval +address: 0x643 +long_name: Hypervisor Trap Value Register +description: | + When a trap is taken into HS-mode, htval is written with additional exception-specific information, alongside stval, to assist software in handling the trap. - When a guest-page-fault trap is taken into HS-mode, htval is written with either zero or the guest physical address that faulted, shifted right by 2 bits. For other traps, htval is set to zero, but a future standard or extension may redefine htval's setting for other traps. + When a guest-page-fault trap is taken into HS-mode, htval is written with either zero or the guest physical address that faulted, shifted right by 2 bits. For other traps, htval is set to zero, but a future standard or extension may redefine htval's setting for other traps. - A guest-page fault may arise due to an implicit memory access during first-stage (VS-stage) address translation, in which case a guest physical address written to htval is that of the implicit memory access that faulted-for example, the address of a VS-level page table entry that could not be read. (The guest physical address corresponding to the original virtual address is unknown when VS-stage translation fails to complete.) Additional information is provided in CSR htinst to disambiguate such situations. + A guest-page fault may arise due to an implicit memory access during first-stage (VS-stage) address translation, in which case a guest physical address written to htval is that of the implicit memory access that faulted-for example, the address of a VS-level page table entry that could not be read. (The guest physical address corresponding to the original virtual address is unknown when VS-stage translation fails to complete.) Additional information is provided in CSR htinst to disambiguate such situations. - Otherwise, for misaligned loads and stores that cause guest-page faults, a nonzero guest physical address in htval corresponds to the faulting portion of the access as indicated by the virtual address in stval. For instruction guest-page faults on systems with variable-length instructions, a nonzero htval corresponds to the faulting portion of the instruction as indicated by the virtual address in stval. + Otherwise, for misaligned loads and stores that cause guest-page faults, a nonzero guest physical address in htval corresponds to the faulting portion of the access as indicated by the virtual address in stval. For instruction guest-page faults on systems with variable-length instructions, a nonzero htval corresponds to the faulting portion of the instruction as indicated by the virtual address in stval. - htval is a WARL register that must be able to hold zero and may be capable of holding only an arbitrary subset of other 2-bit-shifted guest physical addresses, if any. - priv_mode: M - length: MXLEN - definedBy: H - fields: - VALUE: - location_rv64: 63-0 - location_rv32: 31-0 - type(): | - if (REPORT_GPA_IN_TVAL_ON_LOAD_GUEST_PAGE_FAULT - || REPORT_GPA_IN_TVAL_ON_STORE_AMO_GUEST_PAGE_FAULT - || REPORT_GPA_IN_TVAL_ON_INSTRUCTION_GUEST_PAGE_FAULT - || REPORT_GPA_IN_TVAL_ON_INTERMEDIATE_GUEST_PAGE_FAULT) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - description: | - Exception-speicific information for a trap into M-mode. - reset_value: UNDEFINED_LEGAL + htval is a WARL register that must be able to hold zero and may be capable of holding only an arbitrary subset of other 2-bit-shifted guest physical addresses, if any. +priv_mode: M +length: MXLEN +definedBy: H +fields: + VALUE: + location_rv64: 63-0 + location_rv32: 31-0 + type(): | + if (REPORT_GPA_IN_TVAL_ON_LOAD_GUEST_PAGE_FAULT + || REPORT_GPA_IN_TVAL_ON_STORE_AMO_GUEST_PAGE_FAULT + || REPORT_GPA_IN_TVAL_ON_INSTRUCTION_GUEST_PAGE_FAULT + || REPORT_GPA_IN_TVAL_ON_INTERMEDIATE_GUEST_PAGE_FAULT) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + description: | + Exception-speicific information for a trap into M-mode. + reset_value: UNDEFINED_LEGAL diff --git a/arch/csr/H/mtinst.yaml b/arch/csr/H/mtinst.yaml index ff3f34ed6..64a6af0a0 100644 --- a/arch/csr/H/mtinst.yaml +++ b/arch/csr/H/mtinst.yaml @@ -1,42 +1,44 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mtinst: - address: 0x34a - long_name: Machine Trap Instruction Register - description: | - When a trap is taken into M-mode, mtinst is written with a value that, if nonzero, - provides information about the instruction that trapped, to assist software in handling the trap. - The values that may be written to mtinst on a trap are documented in TODO. +$schema: "csr_schema.json#" +kind: csr +name: mtinst +address: 0x34a +long_name: Machine Trap Instruction Register +description: | + When a trap is taken into M-mode, mtinst is written with a value that, if nonzero, + provides information about the instruction that trapped, to assist software in handling the trap. + The values that may be written to mtinst on a trap are documented in TODO. - mtinst is a WARL register that need only be able to hold the values that the implementation may automatically write to it on a trap. - priv_mode: M - length: MXLEN - definedBy: H - fields: - VALUE: - location_rv64: 63-0 - location_rv32: 31-0 - type(): | - if ( (TINST_VALUE_ON_FINAL_LOAD_GUEST_PAGE_FAULT != "always zero") - || (TINST_VALUE_ON_FINAL_STORE_AMO_GUEST_PAGE_FAULT != "always zero") - || (TINST_VALUE_ON_FINAL_INSTRUCTION_GUEST_PAGE_FAULT != "always zero") - || (TINST_VALUE_ON_INSTRUCTION_ADDRESS_MISALIGNED != "always zero") - || (TINST_VALUE_ON_BREAKPOINT != "always zero") - || (TINST_VALUE_ON_VIRTUAL_INSTRUCTION != "always zero") - || (TINST_VALUE_ON_LOAD_ADDRESS_MISALIGNED != "always zero") - || (TINST_VALUE_ON_LOAD_ACCESS_FAULT != "always zero") - || (TINST_VALUE_ON_STORE_AMO_ADDRESS_MISALIGNED != "always zero") - || (TINST_VALUE_ON_STORE_AMO_ACCESS_FAULT != "always_zero") - || (TINST_VALUE_ON_UCALL != "always zero") - || (TINST_VALUE_ON_SCALL != "always zero") - || (TINST_VALUE_ON_MCALL != "always zero") - || (TINST_VALUE_ON_VSCALL != "always zero") - || (TINST_VALUE_ON_LOAD_PAGE_FAULT != "always zero") - || (TINST_VALUE_ON_STORE_AMO_PAGE_FAULT != "always zero")) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - description: | - Exception-speicific information for a trap into M-mode. - reset_value: UNDEFINED_LEGAL + mtinst is a WARL register that need only be able to hold the values that the implementation may automatically write to it on a trap. +priv_mode: M +length: MXLEN +definedBy: H +fields: + VALUE: + location_rv64: 63-0 + location_rv32: 31-0 + type(): | + if ( (TINST_VALUE_ON_FINAL_LOAD_GUEST_PAGE_FAULT != "always zero") + || (TINST_VALUE_ON_FINAL_STORE_AMO_GUEST_PAGE_FAULT != "always zero") + || (TINST_VALUE_ON_FINAL_INSTRUCTION_GUEST_PAGE_FAULT != "always zero") + || (TINST_VALUE_ON_INSTRUCTION_ADDRESS_MISALIGNED != "always zero") + || (TINST_VALUE_ON_BREAKPOINT != "always zero") + || (TINST_VALUE_ON_VIRTUAL_INSTRUCTION != "always zero") + || (TINST_VALUE_ON_LOAD_ADDRESS_MISALIGNED != "always zero") + || (TINST_VALUE_ON_LOAD_ACCESS_FAULT != "always zero") + || (TINST_VALUE_ON_STORE_AMO_ADDRESS_MISALIGNED != "always zero") + || (TINST_VALUE_ON_STORE_AMO_ACCESS_FAULT != "always_zero") + || (TINST_VALUE_ON_UCALL != "always zero") + || (TINST_VALUE_ON_SCALL != "always zero") + || (TINST_VALUE_ON_MCALL != "always zero") + || (TINST_VALUE_ON_VSCALL != "always zero") + || (TINST_VALUE_ON_LOAD_PAGE_FAULT != "always zero") + || (TINST_VALUE_ON_STORE_AMO_PAGE_FAULT != "always zero")) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + description: | + Exception-speicific information for a trap into M-mode. + reset_value: UNDEFINED_LEGAL diff --git a/arch/csr/H/mtval2.yaml b/arch/csr/H/mtval2.yaml index a80228520..eb51a7bb4 100644 --- a/arch/csr/H/mtval2.yaml +++ b/arch/csr/H/mtval2.yaml @@ -1,35 +1,37 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mtval2: - address: 0x34b - long_name: Machine Second Trap Value Register - description: | - When a trap is taken into M-mode from a virtual mode, mtval2 is written with additional exception-specific information, - alongside mtval, to assist software in handling the trap. +$schema: "csr_schema.json#" +kind: csr +name: mtval2 +address: 0x34b +long_name: Machine Second Trap Value Register +description: | + When a trap is taken into M-mode from a virtual mode, mtval2 is written with additional exception-specific information, + alongside mtval, to assist software in handling the trap. - When a guest-page-fault trap is taken into M-mode, mtval2 is written with either zero or the guest physical address that faulted, shifted right by 2 bits. For other traps, mtval2 is set to zero, but a future standard or extension may redefine mtval2's setting for other traps. + When a guest-page-fault trap is taken into M-mode, mtval2 is written with either zero or the guest physical address that faulted, shifted right by 2 bits. For other traps, mtval2 is set to zero, but a future standard or extension may redefine mtval2's setting for other traps. - If a guest-page fault is due to an implicit memory access during first-stage (VS-stage) address translation, a guest physical address written to mtval2 is that of the implicit memory access that faulted. Additional information is provided in CSR mtinst to disambiguate such situations. + If a guest-page fault is due to an implicit memory access during first-stage (VS-stage) address translation, a guest physical address written to mtval2 is that of the implicit memory access that faulted. Additional information is provided in CSR mtinst to disambiguate such situations. - Otherwise, for misaligned loads and stores that cause guest-page faults, a nonzero guest physical address in mtval2 corresponds to the faulting portion of the access as indicated by the virtual address in mtval. For instruction guest-page faults on systems with variable-length instructions, a nonzero mtval2 corresponds to the faulting portion of the instruction as indicated by the virtual address in mtval. + Otherwise, for misaligned loads and stores that cause guest-page faults, a nonzero guest physical address in mtval2 corresponds to the faulting portion of the access as indicated by the virtual address in mtval. For instruction guest-page faults on systems with variable-length instructions, a nonzero mtval2 corresponds to the faulting portion of the instruction as indicated by the virtual address in mtval. - mtval2 is a WARL register that must be able to hold zero and may be capable of holding only an arbitrary subset of other 2-bit-shifted guest physical addresses, if any. - priv_mode: M - length: MXLEN - definedBy: H - fields: - VALUE: - location_rv64: 63-0 - location_rv32: 31-0 - type(): | - if (REPORT_GPA_IN_TVAL_ON_LOAD_GUEST_PAGE_FAULT - || REPORT_GPA_IN_TVAL_ON_STORE_AMO_GUEST_PAGE_FAULT - || REPORT_GPA_IN_TVAL_ON_INSTRUCTION_GUEST_PAGE_FAULT - || REPORT_GPA_IN_TVAL_ON_INTERMEDIATE_GUEST_PAGE_FAULT) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - description: | - Exception-speicific information for a trap into M-mode. - reset_value: UNDEFINED_LEGAL + mtval2 is a WARL register that must be able to hold zero and may be capable of holding only an arbitrary subset of other 2-bit-shifted guest physical addresses, if any. +priv_mode: M +length: MXLEN +definedBy: H +fields: + VALUE: + location_rv64: 63-0 + location_rv32: 31-0 + type(): | + if (REPORT_GPA_IN_TVAL_ON_LOAD_GUEST_PAGE_FAULT + || REPORT_GPA_IN_TVAL_ON_STORE_AMO_GUEST_PAGE_FAULT + || REPORT_GPA_IN_TVAL_ON_INSTRUCTION_GUEST_PAGE_FAULT + || REPORT_GPA_IN_TVAL_ON_INTERMEDIATE_GUEST_PAGE_FAULT) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + description: | + Exception-speicific information for a trap into M-mode. + reset_value: UNDEFINED_LEGAL diff --git a/arch/csr/H/vsatp.yaml b/arch/csr/H/vsatp.yaml index e70d506de..d95e56e45 100644 --- a/arch/csr/H/vsatp.yaml +++ b/arch/csr/H/vsatp.yaml @@ -1,141 +1,143 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -vsatp: - address: 0x280 - virtual_address: 0x180 - long_name: Virtual Supervisor Address Translation and Protection - description: | - The `vsatp` register is a VSXLEN-bit read/write register that is VS-mode's version of supervisor - register `satp`. - When V=1, `vsatp` substitutes for the usual `satp`, so instructions that normally read or modify - `satp` actually access `vsatp` instead. - `vsatp` controls VS-stage address translation, the first stage of two-stage translation for - guest virtual addresses. +$schema: "csr_schema.json#" +kind: csr +name: vsatp +address: 0x280 +virtual_address: 0x180 +long_name: Virtual Supervisor Address Translation and Protection +description: | + The `vsatp` register is a VSXLEN-bit read/write register that is VS-mode's version of supervisor + register `satp`. + When V=1, `vsatp` substitutes for the usual `satp`, so instructions that normally read or modify + `satp` actually access `vsatp` instead. + `vsatp` controls VS-stage address translation, the first stage of two-stage translation for + guest virtual addresses. - The `vsatp` register is considered active for the purposes of the address-translation algorithm - unless the effective privilege mode is U and `hstatus.HU`=0. - However, even when `vsatp` is active, VS-stage page-table entries' A bits must not be set as a - result of speculative execution, unless the effective privilege mode is VS or VU. + The `vsatp` register is considered active for the purposes of the address-translation algorithm + unless the effective privilege mode is U and `hstatus.HU`=0. + However, even when `vsatp` is active, VS-stage page-table entries' A bits must not be set as a + result of speculative execution, unless the effective privilege mode is VS or VU. - [NOTE] - In particular, virtual-machine load/store (`hlv`, 'hlvx', or 'hsv') instructions that are - misspeculatively executed must not cause VS-stage A bits to be set. + [NOTE] + In particular, virtual-machine load/store (`hlv`, 'hlvx', or 'hsv') instructions that are + misspeculatively executed must not cause VS-stage A bits to be set. - When V=0, a write to `vsatp` with an unsupported MODE value is either ignored as it is for - `satp`, or the fields of `vsatp` are treated as WARL in the normal way. - However, when V=1, a write to `satp` with an unsupported MODE value is ignored and no write to - `vsatp` is effected. - priv_mode: VS - length: VSXLEN - definedBy: H - fields: - MODE: - location_rv64: 63-60 - location_rv32: 31 - type: RW-R - description: | - *Translation Mode* + When V=0, a write to `vsatp` with an unsupported MODE value is either ignored as it is for + `satp`, or the fields of `vsatp` are treated as WARL in the normal way. + However, when V=1, a write to `satp` with an unsupported MODE value is ignored and no write to + `vsatp` is effected. +priv_mode: VS +length: VSXLEN +definedBy: H +fields: + MODE: + location_rv64: 63-60 + location_rv32: 31 + type: RW-R + description: | + *Translation Mode* - Controls the current translation mode in VS-mode according to the table below. + Controls the current translation mode in VS-mode according to the table below. - [separator="!",%autowidth] - !=== - ! Value ! Name ! Description + [separator="!",%autowidth] + !=== + ! Value ! Name ! Description - ! 0 ! Bare a! No translation -> virtual address == physical address - <%- if ext?(:Sv39) -%> - ! 8 ! Sv39 ! 39-bit virtual address translation - <%- end -%> - <%- if ext?(:Sv48) -%> - ! 9 ! Sv48 ! 48-bit virtual address translation - <%- end -%> - <%- if ext?(:Sv57) -%> - ! 10 ! Sv57 ! 57-bit virtual address translation - <%- end -%> - !=== + ! 0 ! Bare a! No translation -> virtual address == physical address + <%- if ext?(:Sv39) -%> + ! 8 ! Sv39 ! 39-bit virtual address translation + <%- end -%> + <%- if ext?(:Sv48) -%> + ! 9 ! Sv48 ! 48-bit virtual address translation + <%- end -%> + <%- if ext?(:Sv57) -%> + ! 10 ! Sv57 ! 57-bit virtual address translation + <%- end -%> + !=== - Any other value shall be ignored on a write. - reset_value: UNDEFINED_LEGAL - sw_write(csr_value): | - if (csr_value.MODE == 0) { - if (virtual_mode?() || IGNORE_INVALID_VSATP_MODE_WRITES_WHEN_V_EQ_ZERO) { - # In Bare, ASID and PPN must be zero, else the entire write is ignored - if (csr_value.ASID == 0 && csr_value.PPN == 0) { - return csr_value.MODE; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + Any other value shall be ignored on a write. + reset_value: UNDEFINED_LEGAL + sw_write(csr_value): | + if (csr_value.MODE == 0) { + if (virtual_mode?() || IGNORE_INVALID_VSATP_MODE_WRITES_WHEN_V_EQ_ZERO) { + # In Bare, ASID and PPN must be zero, else the entire write is ignored + if (csr_value.ASID == 0 && csr_value.PPN == 0) { + return csr_value.MODE; } else { return UNDEFINED_LEGAL_DETERMINISTIC; } - } - else if (implemented?(ExtensionName::Sv39) && csr_value.MODE == 8) { return csr_value.MODE; } - else if (implemented?(ExtensionName::Sv48) && csr_value.MODE == 9) { return csr_value.MODE; } - else if (implemented?(ExtensionName::Sv57) && csr_value.MODE == 10) { return csr_value.MODE; } - else { + } else { return UNDEFINED_LEGAL_DETERMINISTIC; } - ASID: - location_rv32: 30-22 - location_rv64: 59-44 - description: | - *Address Space ID* - type: RW-R - sw_write(csr_value): | - if (csr_value.MODE == 0) { - if (virtual_mode?() || IGNORE_INVALID_VSATP_MODE_WRITES_WHEN_V_EQ_ZERO) { - # when MODE == Bare, PPN and ASID must be zero - if (csr_value.ASID == 0 && csr_value.PPN == 0) { - return csr_value.ASID; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + } + else if (implemented?(ExtensionName::Sv39) && csr_value.MODE == 8) { return csr_value.MODE; } + else if (implemented?(ExtensionName::Sv48) && csr_value.MODE == 9) { return csr_value.MODE; } + else if (implemented?(ExtensionName::Sv57) && csr_value.MODE == 10) { return csr_value.MODE; } + else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } + ASID: + location_rv32: 30-22 + location_rv64: 59-44 + description: | + *Address Space ID* + type: RW-R + sw_write(csr_value): | + if (csr_value.MODE == 0) { + if (virtual_mode?() || IGNORE_INVALID_VSATP_MODE_WRITES_WHEN_V_EQ_ZERO) { + # when MODE == Bare, PPN and ASID must be zero + if (csr_value.ASID == 0 && csr_value.PPN == 0) { + return csr_value.ASID; } else { return UNDEFINED_LEGAL_DETERMINISTIC; } } else { - XReg shamt = ((XLEN == 32) || (CSR[mstatus].SXL == $bits(XRegWidth::XLEN32))) ? 9 : 16; - XReg all_ones = ((1 << shamt) - 1); - XReg largest_allowed_asid = (1 << shamt) - 1; + return UNDEFINED_LEGAL_DETERMINISTIC; + } + } else { + XReg shamt = ((XLEN == 32) || (CSR[mstatus].SXL == $bits(XRegWidth::XLEN32))) ? 9 : 16; + XReg all_ones = ((1 << shamt) - 1); + XReg largest_allowed_asid = (1 << shamt) - 1; - if (csr_value.ASID == all_ones) { - # the specification states that if all 1's are written to the ASID field, then - # you must return the largest asid - return largest_allowed_asid; - } else if (csr_value.ASID > largest_allowed_asid) { - # ... but is silent on what happens on any other illegal value - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - # unrestricted - return csr_value.ASID; - } + if (csr_value.ASID == all_ones) { + # the specification states that if all 1's are written to the ASID field, then + # you must return the largest asid + return largest_allowed_asid; + } else if (csr_value.ASID > largest_allowed_asid) { + # ... but is silent on what happens on any other illegal value + return UNDEFINED_LEGAL_DETERMINISTIC; + } else { + # unrestricted + return csr_value.ASID; } - reset_value: UNDEFINED_LEGAL - PPN: - location_rv32: 21-0 - location_rv64: 43-0 - description: | - *Physical Page Number* + } + reset_value: UNDEFINED_LEGAL + PPN: + location_rv32: 21-0 + location_rv64: 43-0 + description: | + *Physical Page Number* - The physical address of the active root page table is PPN << 12. + The physical address of the active root page table is PPN << 12. - Can only hold values that correspond to a valid page table base, which - will be implementation-dependent. - type: RW-R - reset_value: UNDEFINED_LEGAL - sw_write(csr_value): | - if (csr_value.MODE == 0) { - if (virtual_mode?() || IGNORE_INVALID_VSATP_MODE_WRITES_WHEN_V_EQ_ZERO) { - # when MODE == Bare, PPN and ASID must be zero - if (csr_value.ASID == 0 && csr_value.PPN == 0) { - return csr_value.PPN; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + Can only hold values that correspond to a valid page table base, which + will be implementation-dependent. + type: RW-R + reset_value: UNDEFINED_LEGAL + sw_write(csr_value): | + if (csr_value.MODE == 0) { + if (virtual_mode?() || IGNORE_INVALID_VSATP_MODE_WRITES_WHEN_V_EQ_ZERO) { + # when MODE == Bare, PPN and ASID must be zero + if (csr_value.ASID == 0 && csr_value.PPN == 0) { + return csr_value.PPN; } else { return UNDEFINED_LEGAL_DETERMINISTIC; } } else { - # unrestricted - return csr_value.PPN; + return UNDEFINED_LEGAL_DETERMINISTIC; } + } else { + # unrestricted + return csr_value.PPN; + } diff --git a/arch/csr/I/mcounteren.layout b/arch/csr/I/mcounteren.layout index d734fe722..ca2fd30fd 100644 --- a/arch/csr/I/mcounteren.layout +++ b/arch/csr/I/mcounteren.layout @@ -1,186 +1,188 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mcounteren: - long_name: Machine Counter Enable - address: 0x306 - priv_mode: M - length: 32 - description: | - The counter-enable `mcounteren` register is a 32-bit register that controls the availability - of the hardware performance-monitoring counters to - <%%- if ext?(:S) -%> - S-mode - <%%- elsif ext?(:U) -%> - U-mode - <%%- else -%> - the next-lower privileged mode - <%%- end -%> - . - - The settings in this register only control accessibility. The act of reading or writing this - register does not affect the underlying counters, which continue to increment even when not - accessible. - - When the CY, TM, IR, or HPMn bit in the mcounteren register is clear, attempts to read the - `cycle`, `time`, `instret`, or `hpmcountern` register while executing in - <%%- if ext?(:S) -%> - S-mode - <%%- elsif ext?(:U) -%> - U-mode - <%%- else -%> - S-mode or U-mode - <%%- end -%> - will cause an `IllegalInstruction` exception. When one of these bits is set, access to the - corresponding register is permitted in - <%%- if ext?(:S) -%> - S-mode - <%%- elsif ext?(:U) -%> - U-mode - <%%- else -%> - the next implemented privilege mode (S-mode if implemented, otherwise U-mode). - <%%- end -%> - - [NOTE] - The counter-enable bits support two common use cases with minimal hardware. - For harts that do not need high-performance timers and counters, machine-mode software can - trap accesses and implement all features in software. For harts that need high-performance - timers and counters but are not concerned with obfuscating the underlying hardware counters, - the counters can be directly exposed to lower privilege modes. - - The `cycle`, `instret`, and `hpmcountern` CSRs are read-only shadows of `mcycle`, `minstret`, - and `mhpmcounter n`, respectively. The `time` CSR is a read-only shadow of the memory-mapped - `mtime` register. - <%%- if possible_xlens.include?(32) -%> - Analogously, on RV32I the `cycleh`, `instreth` and `hpmcounternh` CSRs are - read-only shadows of `mcycleh`, `minstreth` and `mhpmcounternh`, respectively. - On RV32I the `timeh` CSR is a read-only shadow of the upper 32 bits of the memory-mapped `mtime` - register, while time shadows only the lower 32 bits of `mtime`. - <%%- end -%> - - [NOTE] - Implementations can convert reads of the `time` and `timeh` CSRs into loads to the - memory-mapped `mtime` register, or emulate this functionality on behalf of less-privileged - modes in M-mode software. - - <%%- if !ext?(:U) -%> - In harts with U-mode, the `mcounteren` CSR must be implemented, but all fields are WARL and may - be read-only zero, indicating reads to the corresponding counter will cause an - `IllegalInstruction` exception when executing in a less-privileged mode. - In harts without U-mode, the `mcounteren` register should not exist. - <%%- end -%> - - <%%- if ext?(:S) -%> - [INFO] - The `cycle`, `instret`, and `hpmcountern` CSRs can also be made available to U-mode - through the `scounteren` CSR - <%%- if ext?(:H) -%> - and to VS-mode and/or VU-mode through `hcounteren` - <%%- end -%> - . - <%%- end -%> - - - definedBy: U # actually, defined by RV64, but must implement U-mode for this CSR to exist - fields: - CY: - location: 0 - description: | - When set, the `cycle` CSR (an alias of `mcycle`) is accessible to - <%%- if ext?(:S) -%> - S-mode. - <%%- else -%> - U-mode. - <%%- end -%> - - <%%- if ext?(:S) -%> - When `scounteren.CY` is also set, `cycle` is futher accessible to U-mode. - <%%- end -%> - - <%%- if ext?(:H) -%> - When `hcounteren.CY` is also set, `cycle` is futher accessible to VS-mode. - - When `hcounteren.CY` && `scounteren.CY` are both set, `cycle` is futher accessible to VU-mode. - <%%- end -%> - type(): | - if (MCOUNTENABLE_EN[2]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[2]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - TM: - location: 1 - description: | - Placeholder for delegating `time` to less-privileged modes; however, since `time` - is memory-mapped rather than a CSR, this field is always read-only zero. - type: RO - reset_value: 0 - IR: - location: 2 - description: | - When set, the `instret` CSR (an alias of `minstret`) is accessible to - <%%- if ext?(:S) -%> - S-mode. - <%%- else -%> - U-mode. - <%%- end -%> - - <%%- if ext?(:S) -%> - When `scounteren.IR` is also set, `instret` is futher accessible to U-mode. - <%%- end -%> - - <%%- if ext?(:H) -%> - When `hcounteren.IR` is also set, `instret` is futher accessible to VS-mode. - - When `hcounteren.IR` && `scounteren.IR` are both set, `instret` is futher accessible to VU-mode. - <%%- end -%> - type(): | - if (MCOUNTENABLE_EN[2]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[2]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - <%- (3..31).each do |hpm_num| -%> - HPM<%= hpm_num %>: - location: <%= hpm_num %> - description: | - When set, the `hpmcounter<%= hpm_num %>` CSR (an alias of `mhpmcounter<%= hpm_num %>`) is accessible to - <%%- if ext?(:S) -%> - S-mode. - <%%- else -%> - U-mode. - <%%- end -%> - - <%%- if ext?(:S) -%> - When `scounteren.HPM<%= hpm_num %>` is also set, `hpmcounter<%= hpm_num %>` is futher accessible to U-mode. - <%%- end -%> - - <%%- if ext?(:H) -%> - When `hcounteren.HPM<%= hpm_num %>` is also set, `hpmcounter<%= hpm_num %>` is futher accessible to VS-mode. - - When `hcounteren.HPM<%= hpm_num %>` && `scounteren.HPM<%= hpm_num %>` are both set, `hpmcounter<%= hpm_num %>` is futher accessible to VU-mode. - <%%- end -%> - type(): | - if (MCOUNTENABLE_EN[<%= hpm_num %>]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[<%= hpm_num %>]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - <%- end -%> +$schema: csr_schema.json# +kind: csr +name: mcounteren +long_name: Machine Counter Enable +address: 0x306 +priv_mode: M +length: 32 +description: | + The counter-enable `mcounteren` register is a 32-bit register that controls the availability + of the hardware performance-monitoring counters to + <%%- if ext?(:S) -%> + S-mode + <%%- elsif ext?(:U) -%> + U-mode + <%%- else -%> + the next-lower privileged mode + <%%- end -%> + . + + The settings in this register only control accessibility. The act of reading or writing this + register does not affect the underlying counters, which continue to increment even when not + accessible. + + When the CY, TM, IR, or HPMn bit in the mcounteren register is clear, attempts to read the + `cycle`, `time`, `instret`, or `hpmcountern` register while executing in + <%%- if ext?(:S) -%> + S-mode + <%%- elsif ext?(:U) -%> + U-mode + <%%- else -%> + S-mode or U-mode + <%%- end -%> + will cause an `IllegalInstruction` exception. When one of these bits is set, access to the + corresponding register is permitted in + <%%- if ext?(:S) -%> + S-mode + <%%- elsif ext?(:U) -%> + U-mode + <%%- else -%> + the next implemented privilege mode (S-mode if implemented, otherwise U-mode). + <%%- end -%> + + [NOTE] + The counter-enable bits support two common use cases with minimal hardware. + For harts that do not need high-performance timers and counters, machine-mode software can + trap accesses and implement all features in software. For harts that need high-performance + timers and counters but are not concerned with obfuscating the underlying hardware counters, + the counters can be directly exposed to lower privilege modes. + + The `cycle`, `instret`, and `hpmcountern` CSRs are read-only shadows of `mcycle`, `minstret`, + and `mhpmcounter n`, respectively. The `time` CSR is a read-only shadow of the memory-mapped + `mtime` register. + <%%- if possible_xlens.include?(32) -%> + Analogously, on RV32I the `cycleh`, `instreth` and `hpmcounternh` CSRs are + read-only shadows of `mcycleh`, `minstreth` and `mhpmcounternh`, respectively. + On RV32I the `timeh` CSR is a read-only shadow of the upper 32 bits of the memory-mapped `mtime` + register, while time shadows only the lower 32 bits of `mtime`. + <%%- end -%> + + [NOTE] + Implementations can convert reads of the `time` and `timeh` CSRs into loads to the + memory-mapped `mtime` register, or emulate this functionality on behalf of less-privileged + modes in M-mode software. + + <%%- if !ext?(:U) -%> + In harts with U-mode, the `mcounteren` CSR must be implemented, but all fields are WARL and may + be read-only zero, indicating reads to the corresponding counter will cause an + `IllegalInstruction` exception when executing in a less-privileged mode. + In harts without U-mode, the `mcounteren` register should not exist. + <%%- end -%> + + <%%- if ext?(:S) -%> + [INFO] + The `cycle`, `instret`, and `hpmcountern` CSRs can also be made available to U-mode + through the `scounteren` CSR + <%%- if ext?(:H) -%> + and to VS-mode and/or VU-mode through `hcounteren` + <%%- end -%> + . + <%%- end -%> + + +definedBy: U # actually, defined by RV64, but must implement U-mode for this CSR to exist +fields: + CY: + location: 0 + description: | + When set, the `cycle` CSR (an alias of `mcycle`) is accessible to + <%%- if ext?(:S) -%> + S-mode. + <%%- else -%> + U-mode. + <%%- end -%> + + <%%- if ext?(:S) -%> + When `scounteren.CY` is also set, `cycle` is futher accessible to U-mode. + <%%- end -%> + + <%%- if ext?(:H) -%> + When `hcounteren.CY` is also set, `cycle` is futher accessible to VS-mode. + + When `hcounteren.CY` && `scounteren.CY` are both set, `cycle` is futher accessible to VU-mode. + <%%- end -%> + type(): | + if (MCOUNTENABLE_EN[2]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[2]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + TM: + location: 1 + description: | + Placeholder for delegating `time` to less-privileged modes; however, since `time` + is memory-mapped rather than a CSR, this field is always read-only zero. + type: RO + reset_value: 0 + IR: + location: 2 + description: | + When set, the `instret` CSR (an alias of `minstret`) is accessible to + <%%- if ext?(:S) -%> + S-mode. + <%%- else -%> + U-mode. + <%%- end -%> + + <%%- if ext?(:S) -%> + When `scounteren.IR` is also set, `instret` is futher accessible to U-mode. + <%%- end -%> + + <%%- if ext?(:H) -%> + When `hcounteren.IR` is also set, `instret` is futher accessible to VS-mode. + + When `hcounteren.IR` && `scounteren.IR` are both set, `instret` is futher accessible to VU-mode. + <%%- end -%> + type(): | + if (MCOUNTENABLE_EN[2]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[2]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + <%- (3..31).each do |hpm_num| -%> + HPM<%= hpm_num %>: + location: <%= hpm_num %> + description: | + When set, the `hpmcounter<%= hpm_num %>` CSR (an alias of `mhpmcounter<%= hpm_num %>`) is accessible to + <%%- if ext?(:S) -%> + S-mode. + <%%- else -%> + U-mode. + <%%- end -%> + + <%%- if ext?(:S) -%> + When `scounteren.HPM<%= hpm_num %>` is also set, `hpmcounter<%= hpm_num %>` is futher accessible to U-mode. + <%%- end -%> + + <%%- if ext?(:H) -%> + When `hcounteren.HPM<%= hpm_num %>` is also set, `hpmcounter<%= hpm_num %>` is futher accessible to VS-mode. + + When `hcounteren.HPM<%= hpm_num %>` && `scounteren.HPM<%= hpm_num %>` are both set, `hpmcounter<%= hpm_num %>` is futher accessible to VU-mode. + <%%- end -%> + type(): | + if (MCOUNTENABLE_EN[<%= hpm_num %>]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[<%= hpm_num %>]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + <%- end -%> diff --git a/arch/csr/I/mcounteren.yaml b/arch/csr/I/mcounteren.yaml index 8b12aecea..27bc7ff46 100644 --- a/arch/csr/I/mcounteren.yaml +++ b/arch/csr/I/mcounteren.yaml @@ -3,1053 +3,1055 @@ # WARNING: This file is auto-generated from arch/csr/I/mcounteren.layout -mcounteren: - long_name: Machine Counter Enable - address: 0x306 - priv_mode: M - length: 32 - description: | - The counter-enable `mcounteren` register is a 32-bit register that controls the availability - of the hardware performance-monitoring counters to - <%- if ext?(:S) -%> - S-mode - <%- elsif ext?(:U) -%> - U-mode - <%- else -%> - the next-lower privileged mode - <%- end -%> - . - - The settings in this register only control accessibility. The act of reading or writing this - register does not affect the underlying counters, which continue to increment even when not - accessible. - - When the CY, TM, IR, or HPMn bit in the mcounteren register is clear, attempts to read the - `cycle`, `time`, `instret`, or `hpmcountern` register while executing in - <%- if ext?(:S) -%> - S-mode - <%- elsif ext?(:U) -%> - U-mode - <%- else -%> - S-mode or U-mode - <%- end -%> - will cause an `IllegalInstruction` exception. When one of these bits is set, access to the - corresponding register is permitted in - <%- if ext?(:S) -%> - S-mode - <%- elsif ext?(:U) -%> - U-mode - <%- else -%> - the next implemented privilege mode (S-mode if implemented, otherwise U-mode). - <%- end -%> - - [NOTE] - The counter-enable bits support two common use cases with minimal hardware. - For harts that do not need high-performance timers and counters, machine-mode software can - trap accesses and implement all features in software. For harts that need high-performance - timers and counters but are not concerned with obfuscating the underlying hardware counters, - the counters can be directly exposed to lower privilege modes. - - The `cycle`, `instret`, and `hpmcountern` CSRs are read-only shadows of `mcycle`, `minstret`, - and `mhpmcounter n`, respectively. The `time` CSR is a read-only shadow of the memory-mapped - `mtime` register. - <%- if possible_xlens.include?(32) -%> - Analogously, on RV32I the `cycleh`, `instreth` and `hpmcounternh` CSRs are - read-only shadows of `mcycleh`, `minstreth` and `mhpmcounternh`, respectively. - On RV32I the `timeh` CSR is a read-only shadow of the upper 32 bits of the memory-mapped `mtime` - register, while time shadows only the lower 32 bits of `mtime`. - <%- end -%> - - [NOTE] - Implementations can convert reads of the `time` and `timeh` CSRs into loads to the - memory-mapped `mtime` register, or emulate this functionality on behalf of less-privileged - modes in M-mode software. - - <%- if !ext?(:U) -%> - In harts with U-mode, the `mcounteren` CSR must be implemented, but all fields are WARL and may - be read-only zero, indicating reads to the corresponding counter will cause an - `IllegalInstruction` exception when executing in a less-privileged mode. - In harts without U-mode, the `mcounteren` register should not exist. - <%- end -%> - - <%- if ext?(:S) -%> - [INFO] - The `cycle`, `instret`, and `hpmcountern` CSRs can also be made available to U-mode - through the `scounteren` CSR - <%- if ext?(:H) -%> - and to VS-mode and/or VU-mode through `hcounteren` - <%- end -%> - . - <%- end -%> - - - definedBy: U # actually, defined by RV64, but must implement U-mode for this CSR to exist - fields: - CY: - location: 0 - description: | - When set, the `cycle` CSR (an alias of `mcycle`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.CY` is also set, `cycle` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.CY` is also set, `cycle` is futher accessible to VS-mode. - - When `hcounteren.CY` && `scounteren.CY` are both set, `cycle` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[2]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[2]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - TM: - location: 1 - description: | - Placeholder for delegating `time` to less-privileged modes; however, since `time` - is memory-mapped rather than a CSR, this field is always read-only zero. - type: RO - reset_value: 0 - IR: - location: 2 - description: | - When set, the `instret` CSR (an alias of `minstret`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.IR` is also set, `instret` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.IR` is also set, `instret` is futher accessible to VS-mode. - - When `hcounteren.IR` && `scounteren.IR` are both set, `instret` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[2]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[2]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM3: - location: 3 - description: | - When set, the `hpmcounter3` CSR (an alias of `mhpmcounter3`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM3` is also set, `hpmcounter3` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM3` is also set, `hpmcounter3` is futher accessible to VS-mode. - - When `hcounteren.HPM3` && `scounteren.HPM3` are both set, `hpmcounter3` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[3]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[3]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM4: - location: 4 - description: | - When set, the `hpmcounter4` CSR (an alias of `mhpmcounter4`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM4` is also set, `hpmcounter4` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM4` is also set, `hpmcounter4` is futher accessible to VS-mode. - - When `hcounteren.HPM4` && `scounteren.HPM4` are both set, `hpmcounter4` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[4]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[4]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM5: - location: 5 - description: | - When set, the `hpmcounter5` CSR (an alias of `mhpmcounter5`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM5` is also set, `hpmcounter5` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM5` is also set, `hpmcounter5` is futher accessible to VS-mode. - - When `hcounteren.HPM5` && `scounteren.HPM5` are both set, `hpmcounter5` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[5]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[5]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM6: - location: 6 - description: | - When set, the `hpmcounter6` CSR (an alias of `mhpmcounter6`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM6` is also set, `hpmcounter6` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM6` is also set, `hpmcounter6` is futher accessible to VS-mode. - - When `hcounteren.HPM6` && `scounteren.HPM6` are both set, `hpmcounter6` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[6]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[6]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM7: - location: 7 - description: | - When set, the `hpmcounter7` CSR (an alias of `mhpmcounter7`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM7` is also set, `hpmcounter7` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM7` is also set, `hpmcounter7` is futher accessible to VS-mode. - - When `hcounteren.HPM7` && `scounteren.HPM7` are both set, `hpmcounter7` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[7]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[7]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM8: - location: 8 - description: | - When set, the `hpmcounter8` CSR (an alias of `mhpmcounter8`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM8` is also set, `hpmcounter8` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM8` is also set, `hpmcounter8` is futher accessible to VS-mode. - - When `hcounteren.HPM8` && `scounteren.HPM8` are both set, `hpmcounter8` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[8]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[8]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM9: - location: 9 - description: | - When set, the `hpmcounter9` CSR (an alias of `mhpmcounter9`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM9` is also set, `hpmcounter9` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM9` is also set, `hpmcounter9` is futher accessible to VS-mode. - - When `hcounteren.HPM9` && `scounteren.HPM9` are both set, `hpmcounter9` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[9]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[9]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM10: - location: 10 - description: | - When set, the `hpmcounter10` CSR (an alias of `mhpmcounter10`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM10` is also set, `hpmcounter10` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM10` is also set, `hpmcounter10` is futher accessible to VS-mode. - - When `hcounteren.HPM10` && `scounteren.HPM10` are both set, `hpmcounter10` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[10]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[10]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM11: - location: 11 - description: | - When set, the `hpmcounter11` CSR (an alias of `mhpmcounter11`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM11` is also set, `hpmcounter11` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM11` is also set, `hpmcounter11` is futher accessible to VS-mode. - - When `hcounteren.HPM11` && `scounteren.HPM11` are both set, `hpmcounter11` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[11]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[11]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM12: - location: 12 - description: | - When set, the `hpmcounter12` CSR (an alias of `mhpmcounter12`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM12` is also set, `hpmcounter12` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM12` is also set, `hpmcounter12` is futher accessible to VS-mode. - - When `hcounteren.HPM12` && `scounteren.HPM12` are both set, `hpmcounter12` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[12]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[12]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM13: - location: 13 - description: | - When set, the `hpmcounter13` CSR (an alias of `mhpmcounter13`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM13` is also set, `hpmcounter13` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM13` is also set, `hpmcounter13` is futher accessible to VS-mode. - - When `hcounteren.HPM13` && `scounteren.HPM13` are both set, `hpmcounter13` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[13]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[13]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM14: - location: 14 - description: | - When set, the `hpmcounter14` CSR (an alias of `mhpmcounter14`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM14` is also set, `hpmcounter14` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM14` is also set, `hpmcounter14` is futher accessible to VS-mode. - - When `hcounteren.HPM14` && `scounteren.HPM14` are both set, `hpmcounter14` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[14]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[14]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM15: - location: 15 - description: | - When set, the `hpmcounter15` CSR (an alias of `mhpmcounter15`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM15` is also set, `hpmcounter15` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM15` is also set, `hpmcounter15` is futher accessible to VS-mode. - - When `hcounteren.HPM15` && `scounteren.HPM15` are both set, `hpmcounter15` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[15]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[15]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM16: - location: 16 - description: | - When set, the `hpmcounter16` CSR (an alias of `mhpmcounter16`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM16` is also set, `hpmcounter16` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM16` is also set, `hpmcounter16` is futher accessible to VS-mode. - - When `hcounteren.HPM16` && `scounteren.HPM16` are both set, `hpmcounter16` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[16]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[16]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM17: - location: 17 - description: | - When set, the `hpmcounter17` CSR (an alias of `mhpmcounter17`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM17` is also set, `hpmcounter17` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM17` is also set, `hpmcounter17` is futher accessible to VS-mode. - - When `hcounteren.HPM17` && `scounteren.HPM17` are both set, `hpmcounter17` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[17]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[17]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM18: - location: 18 - description: | - When set, the `hpmcounter18` CSR (an alias of `mhpmcounter18`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM18` is also set, `hpmcounter18` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM18` is also set, `hpmcounter18` is futher accessible to VS-mode. - - When `hcounteren.HPM18` && `scounteren.HPM18` are both set, `hpmcounter18` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[18]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[18]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM19: - location: 19 - description: | - When set, the `hpmcounter19` CSR (an alias of `mhpmcounter19`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM19` is also set, `hpmcounter19` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM19` is also set, `hpmcounter19` is futher accessible to VS-mode. - - When `hcounteren.HPM19` && `scounteren.HPM19` are both set, `hpmcounter19` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[19]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[19]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM20: - location: 20 - description: | - When set, the `hpmcounter20` CSR (an alias of `mhpmcounter20`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM20` is also set, `hpmcounter20` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM20` is also set, `hpmcounter20` is futher accessible to VS-mode. - - When `hcounteren.HPM20` && `scounteren.HPM20` are both set, `hpmcounter20` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[20]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[20]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM21: - location: 21 - description: | - When set, the `hpmcounter21` CSR (an alias of `mhpmcounter21`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM21` is also set, `hpmcounter21` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM21` is also set, `hpmcounter21` is futher accessible to VS-mode. - - When `hcounteren.HPM21` && `scounteren.HPM21` are both set, `hpmcounter21` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[21]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[21]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM22: - location: 22 - description: | - When set, the `hpmcounter22` CSR (an alias of `mhpmcounter22`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM22` is also set, `hpmcounter22` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM22` is also set, `hpmcounter22` is futher accessible to VS-mode. - - When `hcounteren.HPM22` && `scounteren.HPM22` are both set, `hpmcounter22` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[22]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[22]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM23: - location: 23 - description: | - When set, the `hpmcounter23` CSR (an alias of `mhpmcounter23`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM23` is also set, `hpmcounter23` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM23` is also set, `hpmcounter23` is futher accessible to VS-mode. - - When `hcounteren.HPM23` && `scounteren.HPM23` are both set, `hpmcounter23` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[23]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[23]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM24: - location: 24 - description: | - When set, the `hpmcounter24` CSR (an alias of `mhpmcounter24`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM24` is also set, `hpmcounter24` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM24` is also set, `hpmcounter24` is futher accessible to VS-mode. - - When `hcounteren.HPM24` && `scounteren.HPM24` are both set, `hpmcounter24` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[24]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[24]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM25: - location: 25 - description: | - When set, the `hpmcounter25` CSR (an alias of `mhpmcounter25`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM25` is also set, `hpmcounter25` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM25` is also set, `hpmcounter25` is futher accessible to VS-mode. - - When `hcounteren.HPM25` && `scounteren.HPM25` are both set, `hpmcounter25` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[25]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[25]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM26: - location: 26 - description: | - When set, the `hpmcounter26` CSR (an alias of `mhpmcounter26`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM26` is also set, `hpmcounter26` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM26` is also set, `hpmcounter26` is futher accessible to VS-mode. - - When `hcounteren.HPM26` && `scounteren.HPM26` are both set, `hpmcounter26` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[26]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[26]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM27: - location: 27 - description: | - When set, the `hpmcounter27` CSR (an alias of `mhpmcounter27`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM27` is also set, `hpmcounter27` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM27` is also set, `hpmcounter27` is futher accessible to VS-mode. - - When `hcounteren.HPM27` && `scounteren.HPM27` are both set, `hpmcounter27` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[27]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[27]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM28: - location: 28 - description: | - When set, the `hpmcounter28` CSR (an alias of `mhpmcounter28`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM28` is also set, `hpmcounter28` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM28` is also set, `hpmcounter28` is futher accessible to VS-mode. - - When `hcounteren.HPM28` && `scounteren.HPM28` are both set, `hpmcounter28` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[28]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[28]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM29: - location: 29 - description: | - When set, the `hpmcounter29` CSR (an alias of `mhpmcounter29`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM29` is also set, `hpmcounter29` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM29` is also set, `hpmcounter29` is futher accessible to VS-mode. - - When `hcounteren.HPM29` && `scounteren.HPM29` are both set, `hpmcounter29` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[29]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[29]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM30: - location: 30 - description: | - When set, the `hpmcounter30` CSR (an alias of `mhpmcounter30`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM30` is also set, `hpmcounter30` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM30` is also set, `hpmcounter30` is futher accessible to VS-mode. - - When `hcounteren.HPM30` && `scounteren.HPM30` are both set, `hpmcounter30` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[30]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[30]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM31: - location: 31 - description: | - When set, the `hpmcounter31` CSR (an alias of `mhpmcounter31`) is accessible to - <%- if ext?(:S) -%> - S-mode. - <%- else -%> - U-mode. - <%- end -%> - - <%- if ext?(:S) -%> - When `scounteren.HPM31` is also set, `hpmcounter31` is futher accessible to U-mode. - <%- end -%> - - <%- if ext?(:H) -%> - When `hcounteren.HPM31` is also set, `hpmcounter31` is futher accessible to VS-mode. - - When `hcounteren.HPM31` && `scounteren.HPM31` are both set, `hpmcounter31` is futher accessible to VU-mode. - <%- end -%> - type(): | - if (MCOUNTENABLE_EN[31]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (MCOUNTENABLE_EN[31]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mcounteren +long_name: Machine Counter Enable +address: 0x306 +priv_mode: M +length: 32 +description: | + The counter-enable `mcounteren` register is a 32-bit register that controls the availability + of the hardware performance-monitoring counters to + <%- if ext?(:S) -%> + S-mode + <%- elsif ext?(:U) -%> + U-mode + <%- else -%> + the next-lower privileged mode + <%- end -%> + . + + The settings in this register only control accessibility. The act of reading or writing this + register does not affect the underlying counters, which continue to increment even when not + accessible. + + When the CY, TM, IR, or HPMn bit in the mcounteren register is clear, attempts to read the + `cycle`, `time`, `instret`, or `hpmcountern` register while executing in + <%- if ext?(:S) -%> + S-mode + <%- elsif ext?(:U) -%> + U-mode + <%- else -%> + S-mode or U-mode + <%- end -%> + will cause an `IllegalInstruction` exception. When one of these bits is set, access to the + corresponding register is permitted in + <%- if ext?(:S) -%> + S-mode + <%- elsif ext?(:U) -%> + U-mode + <%- else -%> + the next implemented privilege mode (S-mode if implemented, otherwise U-mode). + <%- end -%> + + [NOTE] + The counter-enable bits support two common use cases with minimal hardware. + For harts that do not need high-performance timers and counters, machine-mode software can + trap accesses and implement all features in software. For harts that need high-performance + timers and counters but are not concerned with obfuscating the underlying hardware counters, + the counters can be directly exposed to lower privilege modes. + + The `cycle`, `instret`, and `hpmcountern` CSRs are read-only shadows of `mcycle`, `minstret`, + and `mhpmcounter n`, respectively. The `time` CSR is a read-only shadow of the memory-mapped + `mtime` register. + <%- if possible_xlens.include?(32) -%> + Analogously, on RV32I the `cycleh`, `instreth` and `hpmcounternh` CSRs are + read-only shadows of `mcycleh`, `minstreth` and `mhpmcounternh`, respectively. + On RV32I the `timeh` CSR is a read-only shadow of the upper 32 bits of the memory-mapped `mtime` + register, while time shadows only the lower 32 bits of `mtime`. + <%- end -%> + + [NOTE] + Implementations can convert reads of the `time` and `timeh` CSRs into loads to the + memory-mapped `mtime` register, or emulate this functionality on behalf of less-privileged + modes in M-mode software. + + <%- if !ext?(:U) -%> + In harts with U-mode, the `mcounteren` CSR must be implemented, but all fields are WARL and may + be read-only zero, indicating reads to the corresponding counter will cause an + `IllegalInstruction` exception when executing in a less-privileged mode. + In harts without U-mode, the `mcounteren` register should not exist. + <%- end -%> + + <%- if ext?(:S) -%> + [INFO] + The `cycle`, `instret`, and `hpmcountern` CSRs can also be made available to U-mode + through the `scounteren` CSR + <%- if ext?(:H) -%> + and to VS-mode and/or VU-mode through `hcounteren` + <%- end -%> + . + <%- end -%> + + +definedBy: U # actually, defined by RV64, but must implement U-mode for this CSR to exist +fields: + CY: + location: 0 + description: | + When set, the `cycle` CSR (an alias of `mcycle`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.CY` is also set, `cycle` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.CY` is also set, `cycle` is futher accessible to VS-mode. + + When `hcounteren.CY` && `scounteren.CY` are both set, `cycle` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[2]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[2]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + TM: + location: 1 + description: | + Placeholder for delegating `time` to less-privileged modes; however, since `time` + is memory-mapped rather than a CSR, this field is always read-only zero. + type: RO + reset_value: 0 + IR: + location: 2 + description: | + When set, the `instret` CSR (an alias of `minstret`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.IR` is also set, `instret` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.IR` is also set, `instret` is futher accessible to VS-mode. + + When `hcounteren.IR` && `scounteren.IR` are both set, `instret` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[2]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[2]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM3: + location: 3 + description: | + When set, the `hpmcounter3` CSR (an alias of `mhpmcounter3`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM3` is also set, `hpmcounter3` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM3` is also set, `hpmcounter3` is futher accessible to VS-mode. + + When `hcounteren.HPM3` && `scounteren.HPM3` are both set, `hpmcounter3` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[3]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[3]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM4: + location: 4 + description: | + When set, the `hpmcounter4` CSR (an alias of `mhpmcounter4`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM4` is also set, `hpmcounter4` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM4` is also set, `hpmcounter4` is futher accessible to VS-mode. + + When `hcounteren.HPM4` && `scounteren.HPM4` are both set, `hpmcounter4` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[4]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[4]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM5: + location: 5 + description: | + When set, the `hpmcounter5` CSR (an alias of `mhpmcounter5`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM5` is also set, `hpmcounter5` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM5` is also set, `hpmcounter5` is futher accessible to VS-mode. + + When `hcounteren.HPM5` && `scounteren.HPM5` are both set, `hpmcounter5` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[5]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[5]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM6: + location: 6 + description: | + When set, the `hpmcounter6` CSR (an alias of `mhpmcounter6`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM6` is also set, `hpmcounter6` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM6` is also set, `hpmcounter6` is futher accessible to VS-mode. + + When `hcounteren.HPM6` && `scounteren.HPM6` are both set, `hpmcounter6` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[6]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[6]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM7: + location: 7 + description: | + When set, the `hpmcounter7` CSR (an alias of `mhpmcounter7`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM7` is also set, `hpmcounter7` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM7` is also set, `hpmcounter7` is futher accessible to VS-mode. + + When `hcounteren.HPM7` && `scounteren.HPM7` are both set, `hpmcounter7` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[7]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[7]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM8: + location: 8 + description: | + When set, the `hpmcounter8` CSR (an alias of `mhpmcounter8`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM8` is also set, `hpmcounter8` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM8` is also set, `hpmcounter8` is futher accessible to VS-mode. + + When `hcounteren.HPM8` && `scounteren.HPM8` are both set, `hpmcounter8` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[8]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[8]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM9: + location: 9 + description: | + When set, the `hpmcounter9` CSR (an alias of `mhpmcounter9`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM9` is also set, `hpmcounter9` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM9` is also set, `hpmcounter9` is futher accessible to VS-mode. + + When `hcounteren.HPM9` && `scounteren.HPM9` are both set, `hpmcounter9` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[9]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[9]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM10: + location: 10 + description: | + When set, the `hpmcounter10` CSR (an alias of `mhpmcounter10`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM10` is also set, `hpmcounter10` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM10` is also set, `hpmcounter10` is futher accessible to VS-mode. + + When `hcounteren.HPM10` && `scounteren.HPM10` are both set, `hpmcounter10` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[10]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[10]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM11: + location: 11 + description: | + When set, the `hpmcounter11` CSR (an alias of `mhpmcounter11`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM11` is also set, `hpmcounter11` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM11` is also set, `hpmcounter11` is futher accessible to VS-mode. + + When `hcounteren.HPM11` && `scounteren.HPM11` are both set, `hpmcounter11` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[11]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[11]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM12: + location: 12 + description: | + When set, the `hpmcounter12` CSR (an alias of `mhpmcounter12`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM12` is also set, `hpmcounter12` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM12` is also set, `hpmcounter12` is futher accessible to VS-mode. + + When `hcounteren.HPM12` && `scounteren.HPM12` are both set, `hpmcounter12` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[12]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[12]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM13: + location: 13 + description: | + When set, the `hpmcounter13` CSR (an alias of `mhpmcounter13`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM13` is also set, `hpmcounter13` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM13` is also set, `hpmcounter13` is futher accessible to VS-mode. + + When `hcounteren.HPM13` && `scounteren.HPM13` are both set, `hpmcounter13` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[13]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[13]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM14: + location: 14 + description: | + When set, the `hpmcounter14` CSR (an alias of `mhpmcounter14`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM14` is also set, `hpmcounter14` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM14` is also set, `hpmcounter14` is futher accessible to VS-mode. + + When `hcounteren.HPM14` && `scounteren.HPM14` are both set, `hpmcounter14` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[14]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[14]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM15: + location: 15 + description: | + When set, the `hpmcounter15` CSR (an alias of `mhpmcounter15`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM15` is also set, `hpmcounter15` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM15` is also set, `hpmcounter15` is futher accessible to VS-mode. + + When `hcounteren.HPM15` && `scounteren.HPM15` are both set, `hpmcounter15` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[15]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[15]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM16: + location: 16 + description: | + When set, the `hpmcounter16` CSR (an alias of `mhpmcounter16`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM16` is also set, `hpmcounter16` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM16` is also set, `hpmcounter16` is futher accessible to VS-mode. + + When `hcounteren.HPM16` && `scounteren.HPM16` are both set, `hpmcounter16` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[16]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[16]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM17: + location: 17 + description: | + When set, the `hpmcounter17` CSR (an alias of `mhpmcounter17`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM17` is also set, `hpmcounter17` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM17` is also set, `hpmcounter17` is futher accessible to VS-mode. + + When `hcounteren.HPM17` && `scounteren.HPM17` are both set, `hpmcounter17` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[17]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[17]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM18: + location: 18 + description: | + When set, the `hpmcounter18` CSR (an alias of `mhpmcounter18`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM18` is also set, `hpmcounter18` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM18` is also set, `hpmcounter18` is futher accessible to VS-mode. + + When `hcounteren.HPM18` && `scounteren.HPM18` are both set, `hpmcounter18` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[18]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[18]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM19: + location: 19 + description: | + When set, the `hpmcounter19` CSR (an alias of `mhpmcounter19`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM19` is also set, `hpmcounter19` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM19` is also set, `hpmcounter19` is futher accessible to VS-mode. + + When `hcounteren.HPM19` && `scounteren.HPM19` are both set, `hpmcounter19` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[19]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[19]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM20: + location: 20 + description: | + When set, the `hpmcounter20` CSR (an alias of `mhpmcounter20`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM20` is also set, `hpmcounter20` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM20` is also set, `hpmcounter20` is futher accessible to VS-mode. + + When `hcounteren.HPM20` && `scounteren.HPM20` are both set, `hpmcounter20` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[20]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[20]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM21: + location: 21 + description: | + When set, the `hpmcounter21` CSR (an alias of `mhpmcounter21`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM21` is also set, `hpmcounter21` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM21` is also set, `hpmcounter21` is futher accessible to VS-mode. + + When `hcounteren.HPM21` && `scounteren.HPM21` are both set, `hpmcounter21` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[21]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[21]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM22: + location: 22 + description: | + When set, the `hpmcounter22` CSR (an alias of `mhpmcounter22`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM22` is also set, `hpmcounter22` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM22` is also set, `hpmcounter22` is futher accessible to VS-mode. + + When `hcounteren.HPM22` && `scounteren.HPM22` are both set, `hpmcounter22` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[22]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[22]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM23: + location: 23 + description: | + When set, the `hpmcounter23` CSR (an alias of `mhpmcounter23`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM23` is also set, `hpmcounter23` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM23` is also set, `hpmcounter23` is futher accessible to VS-mode. + + When `hcounteren.HPM23` && `scounteren.HPM23` are both set, `hpmcounter23` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[23]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[23]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM24: + location: 24 + description: | + When set, the `hpmcounter24` CSR (an alias of `mhpmcounter24`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM24` is also set, `hpmcounter24` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM24` is also set, `hpmcounter24` is futher accessible to VS-mode. + + When `hcounteren.HPM24` && `scounteren.HPM24` are both set, `hpmcounter24` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[24]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[24]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM25: + location: 25 + description: | + When set, the `hpmcounter25` CSR (an alias of `mhpmcounter25`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM25` is also set, `hpmcounter25` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM25` is also set, `hpmcounter25` is futher accessible to VS-mode. + + When `hcounteren.HPM25` && `scounteren.HPM25` are both set, `hpmcounter25` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[25]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[25]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM26: + location: 26 + description: | + When set, the `hpmcounter26` CSR (an alias of `mhpmcounter26`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM26` is also set, `hpmcounter26` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM26` is also set, `hpmcounter26` is futher accessible to VS-mode. + + When `hcounteren.HPM26` && `scounteren.HPM26` are both set, `hpmcounter26` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[26]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[26]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM27: + location: 27 + description: | + When set, the `hpmcounter27` CSR (an alias of `mhpmcounter27`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM27` is also set, `hpmcounter27` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM27` is also set, `hpmcounter27` is futher accessible to VS-mode. + + When `hcounteren.HPM27` && `scounteren.HPM27` are both set, `hpmcounter27` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[27]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[27]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM28: + location: 28 + description: | + When set, the `hpmcounter28` CSR (an alias of `mhpmcounter28`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM28` is also set, `hpmcounter28` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM28` is also set, `hpmcounter28` is futher accessible to VS-mode. + + When `hcounteren.HPM28` && `scounteren.HPM28` are both set, `hpmcounter28` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[28]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[28]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM29: + location: 29 + description: | + When set, the `hpmcounter29` CSR (an alias of `mhpmcounter29`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM29` is also set, `hpmcounter29` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM29` is also set, `hpmcounter29` is futher accessible to VS-mode. + + When `hcounteren.HPM29` && `scounteren.HPM29` are both set, `hpmcounter29` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[29]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[29]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM30: + location: 30 + description: | + When set, the `hpmcounter30` CSR (an alias of `mhpmcounter30`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM30` is also set, `hpmcounter30` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM30` is also set, `hpmcounter30` is futher accessible to VS-mode. + + When `hcounteren.HPM30` && `scounteren.HPM30` are both set, `hpmcounter30` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[30]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[30]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM31: + location: 31 + description: | + When set, the `hpmcounter31` CSR (an alias of `mhpmcounter31`) is accessible to + <%- if ext?(:S) -%> + S-mode. + <%- else -%> + U-mode. + <%- end -%> + + <%- if ext?(:S) -%> + When `scounteren.HPM31` is also set, `hpmcounter31` is futher accessible to U-mode. + <%- end -%> + + <%- if ext?(:H) -%> + When `hcounteren.HPM31` is also set, `hpmcounter31` is futher accessible to VS-mode. + + When `hcounteren.HPM31` && `scounteren.HPM31` are both set, `hpmcounter31` is futher accessible to VU-mode. + <%- end -%> + type(): | + if (MCOUNTENABLE_EN[31]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (MCOUNTENABLE_EN[31]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/I/pmpaddr0.yaml b/arch/csr/I/pmpaddr0.yaml index 9a815baab..22ef1b493 100644 --- a/arch/csr/I/pmpaddr0.yaml +++ b/arch/csr/I/pmpaddr0.yaml @@ -4,73 +4,75 @@ -pmpaddr0: - long_name: PMP Address 0 - address: 0x3B0 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 0 - (or, if `pmp1cfg.A` == TOR, for PMP entry 1). - type(): | - if (NUM_PMP_ENTRIES > 0) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 0) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 0) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg0].pmp0cfg[4] == 1)) { - return CSR[pmpaddr0].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg0].pmp0cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr0].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr0 +long_name: PMP Address 0 +address: 0x3B0 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 0 + (or, if `pmp1cfg.A` == TOR, for PMP entry 1). + type(): | + if (NUM_PMP_ENTRIES > 0) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 0) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 0) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr0].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg0].pmp0cfg[4] == 1)) { + return CSR[pmpaddr0].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg0].pmp0cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr0].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg0].pmp0cfg[4] == 1)) { - return CSR[pmpaddr0].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr0].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg0].pmp0cfg[4] == 1)) { + return CSR[pmpaddr0].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg0].pmp0cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr0].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg0].pmp0cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr0].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr0].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr0].ADDR; } + } diff --git a/arch/csr/I/pmpaddr1.yaml b/arch/csr/I/pmpaddr1.yaml index 2b080f834..1c5ccf42b 100644 --- a/arch/csr/I/pmpaddr1.yaml +++ b/arch/csr/I/pmpaddr1.yaml @@ -4,73 +4,75 @@ -pmpaddr1: - long_name: PMP Address 1 - address: 0x3B1 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 1 - (or, if `pmp2cfg.A` == TOR, for PMP entry 2). - type(): | - if (NUM_PMP_ENTRIES > 1) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 1) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 1) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg0].pmp1cfg[4] == 1)) { - return CSR[pmpaddr1].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg0].pmp1cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr1].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr1 +long_name: PMP Address 1 +address: 0x3B1 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 1 + (or, if `pmp2cfg.A` == TOR, for PMP entry 2). + type(): | + if (NUM_PMP_ENTRIES > 1) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 1) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 1) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr1].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg0].pmp1cfg[4] == 1)) { + return CSR[pmpaddr1].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg0].pmp1cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr1].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg0].pmp1cfg[4] == 1)) { - return CSR[pmpaddr1].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr1].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg0].pmp1cfg[4] == 1)) { + return CSR[pmpaddr1].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg0].pmp1cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr1].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg0].pmp1cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr1].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr1].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr1].ADDR; } + } diff --git a/arch/csr/I/pmpaddr10.yaml b/arch/csr/I/pmpaddr10.yaml index f67f9d101..55fc27da3 100644 --- a/arch/csr/I/pmpaddr10.yaml +++ b/arch/csr/I/pmpaddr10.yaml @@ -4,73 +4,75 @@ -pmpaddr10: - long_name: PMP Address 10 - address: 0x3BA - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 10 - (or, if `pmp11cfg.A` == TOR, for PMP entry 11). - type(): | - if (NUM_PMP_ENTRIES > 10) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 10) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 10) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg2].pmp10cfg[4] == 1)) { - return CSR[pmpaddr10].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg2].pmp10cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr10].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr10 +long_name: PMP Address 10 +address: 0x3BA +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 10 + (or, if `pmp11cfg.A` == TOR, for PMP entry 11). + type(): | + if (NUM_PMP_ENTRIES > 10) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 10) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 10) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr10].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg2].pmp10cfg[4] == 1)) { + return CSR[pmpaddr10].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg2].pmp10cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr10].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg2].pmp10cfg[4] == 1)) { - return CSR[pmpaddr10].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr10].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg2].pmp10cfg[4] == 1)) { + return CSR[pmpaddr10].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg2].pmp10cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr10].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg2].pmp10cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr10].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr10].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr10].ADDR; } + } diff --git a/arch/csr/I/pmpaddr11.yaml b/arch/csr/I/pmpaddr11.yaml index 40b919eb6..deca16c14 100644 --- a/arch/csr/I/pmpaddr11.yaml +++ b/arch/csr/I/pmpaddr11.yaml @@ -4,73 +4,75 @@ -pmpaddr11: - long_name: PMP Address 11 - address: 0x3BB - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 11 - (or, if `pmp12cfg.A` == TOR, for PMP entry 12). - type(): | - if (NUM_PMP_ENTRIES > 11) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 11) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 11) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg2].pmp11cfg[4] == 1)) { - return CSR[pmpaddr11].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg2].pmp11cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr11].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr11 +long_name: PMP Address 11 +address: 0x3BB +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 11 + (or, if `pmp12cfg.A` == TOR, for PMP entry 12). + type(): | + if (NUM_PMP_ENTRIES > 11) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 11) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 11) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr11].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg2].pmp11cfg[4] == 1)) { + return CSR[pmpaddr11].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg2].pmp11cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr11].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg2].pmp11cfg[4] == 1)) { - return CSR[pmpaddr11].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr11].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg2].pmp11cfg[4] == 1)) { + return CSR[pmpaddr11].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg2].pmp11cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr11].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg2].pmp11cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr11].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr11].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr11].ADDR; } + } diff --git a/arch/csr/I/pmpaddr12.yaml b/arch/csr/I/pmpaddr12.yaml index ed641e701..bc4a1a004 100644 --- a/arch/csr/I/pmpaddr12.yaml +++ b/arch/csr/I/pmpaddr12.yaml @@ -4,73 +4,75 @@ -pmpaddr12: - long_name: PMP Address 12 - address: 0x3BC - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 12 - (or, if `pmp13cfg.A` == TOR, for PMP entry 13). - type(): | - if (NUM_PMP_ENTRIES > 12) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 12) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 12) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg3].pmp12cfg[4] == 1)) { - return CSR[pmpaddr12].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg3].pmp12cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr12].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr12 +long_name: PMP Address 12 +address: 0x3BC +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 12 + (or, if `pmp13cfg.A` == TOR, for PMP entry 13). + type(): | + if (NUM_PMP_ENTRIES > 12) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 12) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 12) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr12].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg3].pmp12cfg[4] == 1)) { + return CSR[pmpaddr12].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg3].pmp12cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr12].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg2].pmp12cfg[4] == 1)) { - return CSR[pmpaddr12].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr12].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg2].pmp12cfg[4] == 1)) { + return CSR[pmpaddr12].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg2].pmp12cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr12].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg2].pmp12cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr12].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr12].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr12].ADDR; } + } diff --git a/arch/csr/I/pmpaddr13.yaml b/arch/csr/I/pmpaddr13.yaml index e78733593..99b51637a 100644 --- a/arch/csr/I/pmpaddr13.yaml +++ b/arch/csr/I/pmpaddr13.yaml @@ -4,73 +4,75 @@ -pmpaddr13: - long_name: PMP Address 13 - address: 0x3BD - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 13 - (or, if `pmp14cfg.A` == TOR, for PMP entry 14). - type(): | - if (NUM_PMP_ENTRIES > 13) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 13) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 13) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg3].pmp13cfg[4] == 1)) { - return CSR[pmpaddr13].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg3].pmp13cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr13].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr13 +long_name: PMP Address 13 +address: 0x3BD +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 13 + (or, if `pmp14cfg.A` == TOR, for PMP entry 14). + type(): | + if (NUM_PMP_ENTRIES > 13) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 13) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 13) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr13].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg3].pmp13cfg[4] == 1)) { + return CSR[pmpaddr13].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg3].pmp13cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr13].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg2].pmp13cfg[4] == 1)) { - return CSR[pmpaddr13].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr13].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg2].pmp13cfg[4] == 1)) { + return CSR[pmpaddr13].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg2].pmp13cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr13].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg2].pmp13cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr13].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr13].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr13].ADDR; } + } diff --git a/arch/csr/I/pmpaddr14.yaml b/arch/csr/I/pmpaddr14.yaml index 34c46b1b3..0223aa2ab 100644 --- a/arch/csr/I/pmpaddr14.yaml +++ b/arch/csr/I/pmpaddr14.yaml @@ -4,73 +4,75 @@ -pmpaddr14: - long_name: PMP Address 14 - address: 0x3BE - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 14 - (or, if `pmp15cfg.A` == TOR, for PMP entry 15). - type(): | - if (NUM_PMP_ENTRIES > 14) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 14) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 14) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg3].pmp14cfg[4] == 1)) { - return CSR[pmpaddr14].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg3].pmp14cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr14].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr14 +long_name: PMP Address 14 +address: 0x3BE +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 14 + (or, if `pmp15cfg.A` == TOR, for PMP entry 15). + type(): | + if (NUM_PMP_ENTRIES > 14) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 14) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 14) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr14].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg3].pmp14cfg[4] == 1)) { + return CSR[pmpaddr14].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg3].pmp14cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr14].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg2].pmp14cfg[4] == 1)) { - return CSR[pmpaddr14].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr14].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg2].pmp14cfg[4] == 1)) { + return CSR[pmpaddr14].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg2].pmp14cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr14].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg2].pmp14cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr14].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr14].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr14].ADDR; } + } diff --git a/arch/csr/I/pmpaddr15.yaml b/arch/csr/I/pmpaddr15.yaml index 1df6a7640..546579465 100644 --- a/arch/csr/I/pmpaddr15.yaml +++ b/arch/csr/I/pmpaddr15.yaml @@ -4,73 +4,75 @@ -pmpaddr15: - long_name: PMP Address 15 - address: 0x3BF - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 15 - (or, if `pmp16cfg.A` == TOR, for PMP entry 16). - type(): | - if (NUM_PMP_ENTRIES > 15) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 15) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 15) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg3].pmp15cfg[4] == 1)) { - return CSR[pmpaddr15].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg3].pmp15cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr15].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr15 +long_name: PMP Address 15 +address: 0x3BF +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 15 + (or, if `pmp16cfg.A` == TOR, for PMP entry 16). + type(): | + if (NUM_PMP_ENTRIES > 15) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 15) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 15) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr15].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg3].pmp15cfg[4] == 1)) { + return CSR[pmpaddr15].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg3].pmp15cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr15].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg2].pmp15cfg[4] == 1)) { - return CSR[pmpaddr15].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr15].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg2].pmp15cfg[4] == 1)) { + return CSR[pmpaddr15].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg2].pmp15cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr15].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg2].pmp15cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr15].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr15].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr15].ADDR; } + } diff --git a/arch/csr/I/pmpaddr16.yaml b/arch/csr/I/pmpaddr16.yaml index f06f3aaae..8c4a403d8 100644 --- a/arch/csr/I/pmpaddr16.yaml +++ b/arch/csr/I/pmpaddr16.yaml @@ -4,73 +4,75 @@ -pmpaddr16: - long_name: PMP Address 16 - address: 0x3C0 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 16 - (or, if `pmp17cfg.A` == TOR, for PMP entry 17). - type(): | - if (NUM_PMP_ENTRIES > 16) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 16) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 16) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg4].pmp16cfg[4] == 1)) { - return CSR[pmpaddr16].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg4].pmp16cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr16].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr16 +long_name: PMP Address 16 +address: 0x3C0 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 16 + (or, if `pmp17cfg.A` == TOR, for PMP entry 17). + type(): | + if (NUM_PMP_ENTRIES > 16) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 16) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 16) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr16].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg4].pmp16cfg[4] == 1)) { + return CSR[pmpaddr16].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg4].pmp16cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr16].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg4].pmp16cfg[4] == 1)) { - return CSR[pmpaddr16].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr16].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg4].pmp16cfg[4] == 1)) { + return CSR[pmpaddr16].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg4].pmp16cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr16].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg4].pmp16cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr16].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr16].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr16].ADDR; } + } diff --git a/arch/csr/I/pmpaddr17.yaml b/arch/csr/I/pmpaddr17.yaml index bae6ef27f..31ea87ecd 100644 --- a/arch/csr/I/pmpaddr17.yaml +++ b/arch/csr/I/pmpaddr17.yaml @@ -4,73 +4,75 @@ -pmpaddr17: - long_name: PMP Address 17 - address: 0x3C1 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 17 - (or, if `pmp18cfg.A` == TOR, for PMP entry 18). - type(): | - if (NUM_PMP_ENTRIES > 17) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 17) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 17) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg4].pmp17cfg[4] == 1)) { - return CSR[pmpaddr17].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg4].pmp17cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr17].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr17 +long_name: PMP Address 17 +address: 0x3C1 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 17 + (or, if `pmp18cfg.A` == TOR, for PMP entry 18). + type(): | + if (NUM_PMP_ENTRIES > 17) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 17) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 17) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr17].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg4].pmp17cfg[4] == 1)) { + return CSR[pmpaddr17].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg4].pmp17cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr17].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg4].pmp17cfg[4] == 1)) { - return CSR[pmpaddr17].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr17].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg4].pmp17cfg[4] == 1)) { + return CSR[pmpaddr17].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg4].pmp17cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr17].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg4].pmp17cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr17].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr17].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr17].ADDR; } + } diff --git a/arch/csr/I/pmpaddr18.yaml b/arch/csr/I/pmpaddr18.yaml index 886d8974b..42927d3e5 100644 --- a/arch/csr/I/pmpaddr18.yaml +++ b/arch/csr/I/pmpaddr18.yaml @@ -4,73 +4,75 @@ -pmpaddr18: - long_name: PMP Address 18 - address: 0x3C2 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 18 - (or, if `pmp19cfg.A` == TOR, for PMP entry 19). - type(): | - if (NUM_PMP_ENTRIES > 18) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 18) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 18) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg4].pmp18cfg[4] == 1)) { - return CSR[pmpaddr18].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg4].pmp18cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr18].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr18 +long_name: PMP Address 18 +address: 0x3C2 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 18 + (or, if `pmp19cfg.A` == TOR, for PMP entry 19). + type(): | + if (NUM_PMP_ENTRIES > 18) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 18) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 18) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr18].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg4].pmp18cfg[4] == 1)) { + return CSR[pmpaddr18].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg4].pmp18cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr18].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg4].pmp18cfg[4] == 1)) { - return CSR[pmpaddr18].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr18].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg4].pmp18cfg[4] == 1)) { + return CSR[pmpaddr18].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg4].pmp18cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr18].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg4].pmp18cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr18].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr18].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr18].ADDR; } + } diff --git a/arch/csr/I/pmpaddr19.yaml b/arch/csr/I/pmpaddr19.yaml index a9e11125d..1d6d4e332 100644 --- a/arch/csr/I/pmpaddr19.yaml +++ b/arch/csr/I/pmpaddr19.yaml @@ -4,73 +4,75 @@ -pmpaddr19: - long_name: PMP Address 19 - address: 0x3C3 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 19 - (or, if `pmp20cfg.A` == TOR, for PMP entry 20). - type(): | - if (NUM_PMP_ENTRIES > 19) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 19) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 19) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg4].pmp19cfg[4] == 1)) { - return CSR[pmpaddr19].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg4].pmp19cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr19].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr19 +long_name: PMP Address 19 +address: 0x3C3 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 19 + (or, if `pmp20cfg.A` == TOR, for PMP entry 20). + type(): | + if (NUM_PMP_ENTRIES > 19) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 19) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 19) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr19].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg4].pmp19cfg[4] == 1)) { + return CSR[pmpaddr19].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg4].pmp19cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr19].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg4].pmp19cfg[4] == 1)) { - return CSR[pmpaddr19].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr19].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg4].pmp19cfg[4] == 1)) { + return CSR[pmpaddr19].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg4].pmp19cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr19].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg4].pmp19cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr19].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr19].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr19].ADDR; } + } diff --git a/arch/csr/I/pmpaddr2.yaml b/arch/csr/I/pmpaddr2.yaml index 66293dfc9..7b028ad20 100644 --- a/arch/csr/I/pmpaddr2.yaml +++ b/arch/csr/I/pmpaddr2.yaml @@ -4,73 +4,75 @@ -pmpaddr2: - long_name: PMP Address 2 - address: 0x3B2 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 2 - (or, if `pmp3cfg.A` == TOR, for PMP entry 3). - type(): | - if (NUM_PMP_ENTRIES > 2) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 2) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 2) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg0].pmp2cfg[4] == 1)) { - return CSR[pmpaddr2].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg0].pmp2cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr2].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr2 +long_name: PMP Address 2 +address: 0x3B2 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 2 + (or, if `pmp3cfg.A` == TOR, for PMP entry 3). + type(): | + if (NUM_PMP_ENTRIES > 2) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 2) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 2) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr2].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg0].pmp2cfg[4] == 1)) { + return CSR[pmpaddr2].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg0].pmp2cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr2].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg0].pmp2cfg[4] == 1)) { - return CSR[pmpaddr2].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr2].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg0].pmp2cfg[4] == 1)) { + return CSR[pmpaddr2].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg0].pmp2cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr2].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg0].pmp2cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr2].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr2].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr2].ADDR; } + } diff --git a/arch/csr/I/pmpaddr20.yaml b/arch/csr/I/pmpaddr20.yaml index db5aa6977..4706bddad 100644 --- a/arch/csr/I/pmpaddr20.yaml +++ b/arch/csr/I/pmpaddr20.yaml @@ -4,73 +4,75 @@ -pmpaddr20: - long_name: PMP Address 20 - address: 0x3C4 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 20 - (or, if `pmp21cfg.A` == TOR, for PMP entry 21). - type(): | - if (NUM_PMP_ENTRIES > 20) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 20) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 20) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg5].pmp20cfg[4] == 1)) { - return CSR[pmpaddr20].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg5].pmp20cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr20].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr20 +long_name: PMP Address 20 +address: 0x3C4 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 20 + (or, if `pmp21cfg.A` == TOR, for PMP entry 21). + type(): | + if (NUM_PMP_ENTRIES > 20) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 20) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 20) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr20].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg5].pmp20cfg[4] == 1)) { + return CSR[pmpaddr20].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg5].pmp20cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr20].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg4].pmp20cfg[4] == 1)) { - return CSR[pmpaddr20].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr20].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg4].pmp20cfg[4] == 1)) { + return CSR[pmpaddr20].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg4].pmp20cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr20].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg4].pmp20cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr20].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr20].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr20].ADDR; } + } diff --git a/arch/csr/I/pmpaddr21.yaml b/arch/csr/I/pmpaddr21.yaml index 91a2a945f..235ebd088 100644 --- a/arch/csr/I/pmpaddr21.yaml +++ b/arch/csr/I/pmpaddr21.yaml @@ -4,73 +4,75 @@ -pmpaddr21: - long_name: PMP Address 21 - address: 0x3C5 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 21 - (or, if `pmp22cfg.A` == TOR, for PMP entry 22). - type(): | - if (NUM_PMP_ENTRIES > 21) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 21) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 21) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg5].pmp21cfg[4] == 1)) { - return CSR[pmpaddr21].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg5].pmp21cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr21].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr21 +long_name: PMP Address 21 +address: 0x3C5 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 21 + (or, if `pmp22cfg.A` == TOR, for PMP entry 22). + type(): | + if (NUM_PMP_ENTRIES > 21) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 21) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 21) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr21].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg5].pmp21cfg[4] == 1)) { + return CSR[pmpaddr21].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg5].pmp21cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr21].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg4].pmp21cfg[4] == 1)) { - return CSR[pmpaddr21].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr21].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg4].pmp21cfg[4] == 1)) { + return CSR[pmpaddr21].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg4].pmp21cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr21].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg4].pmp21cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr21].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr21].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr21].ADDR; } + } diff --git a/arch/csr/I/pmpaddr22.yaml b/arch/csr/I/pmpaddr22.yaml index bc8712a74..da683c397 100644 --- a/arch/csr/I/pmpaddr22.yaml +++ b/arch/csr/I/pmpaddr22.yaml @@ -4,73 +4,75 @@ -pmpaddr22: - long_name: PMP Address 22 - address: 0x3C6 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 22 - (or, if `pmp23cfg.A` == TOR, for PMP entry 23). - type(): | - if (NUM_PMP_ENTRIES > 22) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 22) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 22) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg5].pmp22cfg[4] == 1)) { - return CSR[pmpaddr22].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg5].pmp22cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr22].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr22 +long_name: PMP Address 22 +address: 0x3C6 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 22 + (or, if `pmp23cfg.A` == TOR, for PMP entry 23). + type(): | + if (NUM_PMP_ENTRIES > 22) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 22) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 22) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr22].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg5].pmp22cfg[4] == 1)) { + return CSR[pmpaddr22].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg5].pmp22cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr22].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg4].pmp22cfg[4] == 1)) { - return CSR[pmpaddr22].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr22].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg4].pmp22cfg[4] == 1)) { + return CSR[pmpaddr22].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg4].pmp22cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr22].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg4].pmp22cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr22].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr22].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr22].ADDR; } + } diff --git a/arch/csr/I/pmpaddr23.yaml b/arch/csr/I/pmpaddr23.yaml index 0889486c7..86fd9e568 100644 --- a/arch/csr/I/pmpaddr23.yaml +++ b/arch/csr/I/pmpaddr23.yaml @@ -4,73 +4,75 @@ -pmpaddr23: - long_name: PMP Address 23 - address: 0x3C7 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 23 - (or, if `pmp24cfg.A` == TOR, for PMP entry 24). - type(): | - if (NUM_PMP_ENTRIES > 23) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 23) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 23) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg5].pmp23cfg[4] == 1)) { - return CSR[pmpaddr23].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg5].pmp23cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr23].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr23 +long_name: PMP Address 23 +address: 0x3C7 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 23 + (or, if `pmp24cfg.A` == TOR, for PMP entry 24). + type(): | + if (NUM_PMP_ENTRIES > 23) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 23) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 23) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr23].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg5].pmp23cfg[4] == 1)) { + return CSR[pmpaddr23].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg5].pmp23cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr23].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg4].pmp23cfg[4] == 1)) { - return CSR[pmpaddr23].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr23].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg4].pmp23cfg[4] == 1)) { + return CSR[pmpaddr23].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg4].pmp23cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr23].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg4].pmp23cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr23].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr23].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr23].ADDR; } + } diff --git a/arch/csr/I/pmpaddr24.yaml b/arch/csr/I/pmpaddr24.yaml index 9c141ba88..eb23278cf 100644 --- a/arch/csr/I/pmpaddr24.yaml +++ b/arch/csr/I/pmpaddr24.yaml @@ -4,73 +4,75 @@ -pmpaddr24: - long_name: PMP Address 24 - address: 0x3C8 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 24 - (or, if `pmp25cfg.A` == TOR, for PMP entry 25). - type(): | - if (NUM_PMP_ENTRIES > 24) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 24) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 24) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg6].pmp24cfg[4] == 1)) { - return CSR[pmpaddr24].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg6].pmp24cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr24].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr24 +long_name: PMP Address 24 +address: 0x3C8 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 24 + (or, if `pmp25cfg.A` == TOR, for PMP entry 25). + type(): | + if (NUM_PMP_ENTRIES > 24) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 24) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 24) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr24].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg6].pmp24cfg[4] == 1)) { + return CSR[pmpaddr24].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg6].pmp24cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr24].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg6].pmp24cfg[4] == 1)) { - return CSR[pmpaddr24].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr24].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg6].pmp24cfg[4] == 1)) { + return CSR[pmpaddr24].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg6].pmp24cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr24].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg6].pmp24cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr24].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr24].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr24].ADDR; } + } diff --git a/arch/csr/I/pmpaddr25.yaml b/arch/csr/I/pmpaddr25.yaml index ae76faa86..779b656eb 100644 --- a/arch/csr/I/pmpaddr25.yaml +++ b/arch/csr/I/pmpaddr25.yaml @@ -4,73 +4,75 @@ -pmpaddr25: - long_name: PMP Address 25 - address: 0x3C9 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 25 - (or, if `pmp26cfg.A` == TOR, for PMP entry 26). - type(): | - if (NUM_PMP_ENTRIES > 25) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 25) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 25) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg6].pmp25cfg[4] == 1)) { - return CSR[pmpaddr25].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg6].pmp25cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr25].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr25 +long_name: PMP Address 25 +address: 0x3C9 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 25 + (or, if `pmp26cfg.A` == TOR, for PMP entry 26). + type(): | + if (NUM_PMP_ENTRIES > 25) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 25) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 25) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr25].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg6].pmp25cfg[4] == 1)) { + return CSR[pmpaddr25].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg6].pmp25cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr25].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg6].pmp25cfg[4] == 1)) { - return CSR[pmpaddr25].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr25].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg6].pmp25cfg[4] == 1)) { + return CSR[pmpaddr25].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg6].pmp25cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr25].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg6].pmp25cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr25].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr25].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr25].ADDR; } + } diff --git a/arch/csr/I/pmpaddr26.yaml b/arch/csr/I/pmpaddr26.yaml index 8a90006b4..6a1b7445e 100644 --- a/arch/csr/I/pmpaddr26.yaml +++ b/arch/csr/I/pmpaddr26.yaml @@ -4,73 +4,75 @@ -pmpaddr26: - long_name: PMP Address 26 - address: 0x3CA - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 26 - (or, if `pmp27cfg.A` == TOR, for PMP entry 27). - type(): | - if (NUM_PMP_ENTRIES > 26) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 26) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 26) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg6].pmp26cfg[4] == 1)) { - return CSR[pmpaddr26].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg6].pmp26cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr26].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr26 +long_name: PMP Address 26 +address: 0x3CA +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 26 + (or, if `pmp27cfg.A` == TOR, for PMP entry 27). + type(): | + if (NUM_PMP_ENTRIES > 26) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 26) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 26) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr26].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg6].pmp26cfg[4] == 1)) { + return CSR[pmpaddr26].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg6].pmp26cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr26].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg6].pmp26cfg[4] == 1)) { - return CSR[pmpaddr26].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr26].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg6].pmp26cfg[4] == 1)) { + return CSR[pmpaddr26].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg6].pmp26cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr26].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg6].pmp26cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr26].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr26].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr26].ADDR; } + } diff --git a/arch/csr/I/pmpaddr27.yaml b/arch/csr/I/pmpaddr27.yaml index cb8aa6462..3960dda99 100644 --- a/arch/csr/I/pmpaddr27.yaml +++ b/arch/csr/I/pmpaddr27.yaml @@ -4,73 +4,75 @@ -pmpaddr27: - long_name: PMP Address 27 - address: 0x3CB - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 27 - (or, if `pmp28cfg.A` == TOR, for PMP entry 28). - type(): | - if (NUM_PMP_ENTRIES > 27) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 27) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 27) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg6].pmp27cfg[4] == 1)) { - return CSR[pmpaddr27].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg6].pmp27cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr27].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr27 +long_name: PMP Address 27 +address: 0x3CB +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 27 + (or, if `pmp28cfg.A` == TOR, for PMP entry 28). + type(): | + if (NUM_PMP_ENTRIES > 27) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 27) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 27) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr27].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg6].pmp27cfg[4] == 1)) { + return CSR[pmpaddr27].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg6].pmp27cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr27].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg6].pmp27cfg[4] == 1)) { - return CSR[pmpaddr27].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr27].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg6].pmp27cfg[4] == 1)) { + return CSR[pmpaddr27].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg6].pmp27cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr27].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg6].pmp27cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr27].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr27].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr27].ADDR; } + } diff --git a/arch/csr/I/pmpaddr28.yaml b/arch/csr/I/pmpaddr28.yaml index 99f3b5bd2..062e089de 100644 --- a/arch/csr/I/pmpaddr28.yaml +++ b/arch/csr/I/pmpaddr28.yaml @@ -4,73 +4,75 @@ -pmpaddr28: - long_name: PMP Address 28 - address: 0x3CC - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 28 - (or, if `pmp29cfg.A` == TOR, for PMP entry 29). - type(): | - if (NUM_PMP_ENTRIES > 28) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 28) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 28) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg7].pmp28cfg[4] == 1)) { - return CSR[pmpaddr28].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg7].pmp28cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr28].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr28 +long_name: PMP Address 28 +address: 0x3CC +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 28 + (or, if `pmp29cfg.A` == TOR, for PMP entry 29). + type(): | + if (NUM_PMP_ENTRIES > 28) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 28) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 28) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr28].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg7].pmp28cfg[4] == 1)) { + return CSR[pmpaddr28].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg7].pmp28cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr28].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg6].pmp28cfg[4] == 1)) { - return CSR[pmpaddr28].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr28].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg6].pmp28cfg[4] == 1)) { + return CSR[pmpaddr28].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg6].pmp28cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr28].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg6].pmp28cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr28].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr28].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr28].ADDR; } + } diff --git a/arch/csr/I/pmpaddr29.yaml b/arch/csr/I/pmpaddr29.yaml index bc8f08681..770c88ddc 100644 --- a/arch/csr/I/pmpaddr29.yaml +++ b/arch/csr/I/pmpaddr29.yaml @@ -4,73 +4,75 @@ -pmpaddr29: - long_name: PMP Address 29 - address: 0x3CD - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 29 - (or, if `pmp30cfg.A` == TOR, for PMP entry 30). - type(): | - if (NUM_PMP_ENTRIES > 29) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 29) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 29) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg7].pmp29cfg[4] == 1)) { - return CSR[pmpaddr29].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg7].pmp29cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr29].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr29 +long_name: PMP Address 29 +address: 0x3CD +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 29 + (or, if `pmp30cfg.A` == TOR, for PMP entry 30). + type(): | + if (NUM_PMP_ENTRIES > 29) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 29) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 29) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr29].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg7].pmp29cfg[4] == 1)) { + return CSR[pmpaddr29].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg7].pmp29cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr29].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg6].pmp29cfg[4] == 1)) { - return CSR[pmpaddr29].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr29].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg6].pmp29cfg[4] == 1)) { + return CSR[pmpaddr29].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg6].pmp29cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr29].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg6].pmp29cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr29].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr29].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr29].ADDR; } + } diff --git a/arch/csr/I/pmpaddr3.yaml b/arch/csr/I/pmpaddr3.yaml index c45b0de9e..b533c5996 100644 --- a/arch/csr/I/pmpaddr3.yaml +++ b/arch/csr/I/pmpaddr3.yaml @@ -4,73 +4,75 @@ -pmpaddr3: - long_name: PMP Address 3 - address: 0x3B3 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 3 - (or, if `pmp4cfg.A` == TOR, for PMP entry 4). - type(): | - if (NUM_PMP_ENTRIES > 3) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 3) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 3) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg0].pmp3cfg[4] == 1)) { - return CSR[pmpaddr3].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg0].pmp3cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr3].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr3 +long_name: PMP Address 3 +address: 0x3B3 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 3 + (or, if `pmp4cfg.A` == TOR, for PMP entry 4). + type(): | + if (NUM_PMP_ENTRIES > 3) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 3) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 3) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr3].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg0].pmp3cfg[4] == 1)) { + return CSR[pmpaddr3].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg0].pmp3cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr3].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg0].pmp3cfg[4] == 1)) { - return CSR[pmpaddr3].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr3].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg0].pmp3cfg[4] == 1)) { + return CSR[pmpaddr3].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg0].pmp3cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr3].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg0].pmp3cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr3].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr3].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr3].ADDR; } + } diff --git a/arch/csr/I/pmpaddr30.yaml b/arch/csr/I/pmpaddr30.yaml index fd640439a..6ef468278 100644 --- a/arch/csr/I/pmpaddr30.yaml +++ b/arch/csr/I/pmpaddr30.yaml @@ -4,73 +4,75 @@ -pmpaddr30: - long_name: PMP Address 30 - address: 0x3CE - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 30 - (or, if `pmp31cfg.A` == TOR, for PMP entry 31). - type(): | - if (NUM_PMP_ENTRIES > 30) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 30) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 30) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg7].pmp30cfg[4] == 1)) { - return CSR[pmpaddr30].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg7].pmp30cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr30].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr30 +long_name: PMP Address 30 +address: 0x3CE +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 30 + (or, if `pmp31cfg.A` == TOR, for PMP entry 31). + type(): | + if (NUM_PMP_ENTRIES > 30) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 30) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 30) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr30].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg7].pmp30cfg[4] == 1)) { + return CSR[pmpaddr30].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg7].pmp30cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr30].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg6].pmp30cfg[4] == 1)) { - return CSR[pmpaddr30].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr30].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg6].pmp30cfg[4] == 1)) { + return CSR[pmpaddr30].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg6].pmp30cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr30].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg6].pmp30cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr30].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr30].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr30].ADDR; } + } diff --git a/arch/csr/I/pmpaddr31.yaml b/arch/csr/I/pmpaddr31.yaml index a792fe968..031f099eb 100644 --- a/arch/csr/I/pmpaddr31.yaml +++ b/arch/csr/I/pmpaddr31.yaml @@ -4,73 +4,75 @@ -pmpaddr31: - long_name: PMP Address 31 - address: 0x3CF - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 31 - (or, if `pmp32cfg.A` == TOR, for PMP entry 32). - type(): | - if (NUM_PMP_ENTRIES > 31) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 31) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 31) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg7].pmp31cfg[4] == 1)) { - return CSR[pmpaddr31].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg7].pmp31cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr31].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr31 +long_name: PMP Address 31 +address: 0x3CF +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 31 + (or, if `pmp32cfg.A` == TOR, for PMP entry 32). + type(): | + if (NUM_PMP_ENTRIES > 31) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 31) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 31) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr31].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg7].pmp31cfg[4] == 1)) { + return CSR[pmpaddr31].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg7].pmp31cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr31].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg6].pmp31cfg[4] == 1)) { - return CSR[pmpaddr31].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr31].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg6].pmp31cfg[4] == 1)) { + return CSR[pmpaddr31].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg6].pmp31cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr31].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg6].pmp31cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr31].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr31].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr31].ADDR; } + } diff --git a/arch/csr/I/pmpaddr32.yaml b/arch/csr/I/pmpaddr32.yaml index a920f8038..9c6b6b9b1 100644 --- a/arch/csr/I/pmpaddr32.yaml +++ b/arch/csr/I/pmpaddr32.yaml @@ -4,73 +4,75 @@ -pmpaddr32: - long_name: PMP Address 32 - address: 0x3D0 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 32 - (or, if `pmp33cfg.A` == TOR, for PMP entry 33). - type(): | - if (NUM_PMP_ENTRIES > 32) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 32) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 32) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg8].pmp32cfg[4] == 1)) { - return CSR[pmpaddr32].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg8].pmp32cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr32].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr32 +long_name: PMP Address 32 +address: 0x3D0 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 32 + (or, if `pmp33cfg.A` == TOR, for PMP entry 33). + type(): | + if (NUM_PMP_ENTRIES > 32) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 32) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 32) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr32].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg8].pmp32cfg[4] == 1)) { + return CSR[pmpaddr32].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg8].pmp32cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr32].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg8].pmp32cfg[4] == 1)) { - return CSR[pmpaddr32].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr32].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg8].pmp32cfg[4] == 1)) { + return CSR[pmpaddr32].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg8].pmp32cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr32].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg8].pmp32cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr32].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr32].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr32].ADDR; } + } diff --git a/arch/csr/I/pmpaddr33.yaml b/arch/csr/I/pmpaddr33.yaml index cb52c645d..6f90b581e 100644 --- a/arch/csr/I/pmpaddr33.yaml +++ b/arch/csr/I/pmpaddr33.yaml @@ -4,73 +4,75 @@ -pmpaddr33: - long_name: PMP Address 33 - address: 0x3D1 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 33 - (or, if `pmp34cfg.A` == TOR, for PMP entry 34). - type(): | - if (NUM_PMP_ENTRIES > 33) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 33) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 33) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg8].pmp33cfg[4] == 1)) { - return CSR[pmpaddr33].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg8].pmp33cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr33].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr33 +long_name: PMP Address 33 +address: 0x3D1 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 33 + (or, if `pmp34cfg.A` == TOR, for PMP entry 34). + type(): | + if (NUM_PMP_ENTRIES > 33) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 33) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 33) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr33].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg8].pmp33cfg[4] == 1)) { + return CSR[pmpaddr33].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg8].pmp33cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr33].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg8].pmp33cfg[4] == 1)) { - return CSR[pmpaddr33].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr33].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg8].pmp33cfg[4] == 1)) { + return CSR[pmpaddr33].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg8].pmp33cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr33].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg8].pmp33cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr33].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr33].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr33].ADDR; } + } diff --git a/arch/csr/I/pmpaddr34.yaml b/arch/csr/I/pmpaddr34.yaml index e993aeb34..64c83a7e5 100644 --- a/arch/csr/I/pmpaddr34.yaml +++ b/arch/csr/I/pmpaddr34.yaml @@ -4,73 +4,75 @@ -pmpaddr34: - long_name: PMP Address 34 - address: 0x3D2 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 34 - (or, if `pmp35cfg.A` == TOR, for PMP entry 35). - type(): | - if (NUM_PMP_ENTRIES > 34) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 34) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 34) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg8].pmp34cfg[4] == 1)) { - return CSR[pmpaddr34].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg8].pmp34cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr34].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr34 +long_name: PMP Address 34 +address: 0x3D2 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 34 + (or, if `pmp35cfg.A` == TOR, for PMP entry 35). + type(): | + if (NUM_PMP_ENTRIES > 34) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 34) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 34) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr34].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg8].pmp34cfg[4] == 1)) { + return CSR[pmpaddr34].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg8].pmp34cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr34].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg8].pmp34cfg[4] == 1)) { - return CSR[pmpaddr34].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr34].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg8].pmp34cfg[4] == 1)) { + return CSR[pmpaddr34].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg8].pmp34cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr34].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg8].pmp34cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr34].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr34].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr34].ADDR; } + } diff --git a/arch/csr/I/pmpaddr35.yaml b/arch/csr/I/pmpaddr35.yaml index e8a742e7b..9ed46e1dd 100644 --- a/arch/csr/I/pmpaddr35.yaml +++ b/arch/csr/I/pmpaddr35.yaml @@ -4,73 +4,75 @@ -pmpaddr35: - long_name: PMP Address 35 - address: 0x3D3 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 35 - (or, if `pmp36cfg.A` == TOR, for PMP entry 36). - type(): | - if (NUM_PMP_ENTRIES > 35) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 35) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 35) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg8].pmp35cfg[4] == 1)) { - return CSR[pmpaddr35].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg8].pmp35cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr35].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr35 +long_name: PMP Address 35 +address: 0x3D3 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 35 + (or, if `pmp36cfg.A` == TOR, for PMP entry 36). + type(): | + if (NUM_PMP_ENTRIES > 35) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 35) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 35) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr35].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg8].pmp35cfg[4] == 1)) { + return CSR[pmpaddr35].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg8].pmp35cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr35].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg8].pmp35cfg[4] == 1)) { - return CSR[pmpaddr35].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr35].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg8].pmp35cfg[4] == 1)) { + return CSR[pmpaddr35].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg8].pmp35cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr35].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg8].pmp35cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr35].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr35].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr35].ADDR; } + } diff --git a/arch/csr/I/pmpaddr36.yaml b/arch/csr/I/pmpaddr36.yaml index 24542cd14..770a97f9a 100644 --- a/arch/csr/I/pmpaddr36.yaml +++ b/arch/csr/I/pmpaddr36.yaml @@ -4,73 +4,75 @@ -pmpaddr36: - long_name: PMP Address 36 - address: 0x3D4 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 36 - (or, if `pmp37cfg.A` == TOR, for PMP entry 37). - type(): | - if (NUM_PMP_ENTRIES > 36) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 36) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 36) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg9].pmp36cfg[4] == 1)) { - return CSR[pmpaddr36].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg9].pmp36cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr36].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr36 +long_name: PMP Address 36 +address: 0x3D4 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 36 + (or, if `pmp37cfg.A` == TOR, for PMP entry 37). + type(): | + if (NUM_PMP_ENTRIES > 36) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 36) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 36) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr36].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg9].pmp36cfg[4] == 1)) { + return CSR[pmpaddr36].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg9].pmp36cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr36].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg8].pmp36cfg[4] == 1)) { - return CSR[pmpaddr36].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr36].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg8].pmp36cfg[4] == 1)) { + return CSR[pmpaddr36].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg8].pmp36cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr36].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg8].pmp36cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr36].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr36].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr36].ADDR; } + } diff --git a/arch/csr/I/pmpaddr37.yaml b/arch/csr/I/pmpaddr37.yaml index 32cdf97a2..a93a78a01 100644 --- a/arch/csr/I/pmpaddr37.yaml +++ b/arch/csr/I/pmpaddr37.yaml @@ -4,73 +4,75 @@ -pmpaddr37: - long_name: PMP Address 37 - address: 0x3D5 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 37 - (or, if `pmp38cfg.A` == TOR, for PMP entry 38). - type(): | - if (NUM_PMP_ENTRIES > 37) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 37) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 37) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg9].pmp37cfg[4] == 1)) { - return CSR[pmpaddr37].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg9].pmp37cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr37].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr37 +long_name: PMP Address 37 +address: 0x3D5 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 37 + (or, if `pmp38cfg.A` == TOR, for PMP entry 38). + type(): | + if (NUM_PMP_ENTRIES > 37) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 37) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 37) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr37].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg9].pmp37cfg[4] == 1)) { + return CSR[pmpaddr37].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg9].pmp37cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr37].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg8].pmp37cfg[4] == 1)) { - return CSR[pmpaddr37].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr37].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg8].pmp37cfg[4] == 1)) { + return CSR[pmpaddr37].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg8].pmp37cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr37].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg8].pmp37cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr37].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr37].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr37].ADDR; } + } diff --git a/arch/csr/I/pmpaddr38.yaml b/arch/csr/I/pmpaddr38.yaml index 709a5ca5e..b74030c19 100644 --- a/arch/csr/I/pmpaddr38.yaml +++ b/arch/csr/I/pmpaddr38.yaml @@ -4,73 +4,75 @@ -pmpaddr38: - long_name: PMP Address 38 - address: 0x3D6 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 38 - (or, if `pmp39cfg.A` == TOR, for PMP entry 39). - type(): | - if (NUM_PMP_ENTRIES > 38) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 38) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 38) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg9].pmp38cfg[4] == 1)) { - return CSR[pmpaddr38].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg9].pmp38cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr38].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr38 +long_name: PMP Address 38 +address: 0x3D6 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 38 + (or, if `pmp39cfg.A` == TOR, for PMP entry 39). + type(): | + if (NUM_PMP_ENTRIES > 38) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 38) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 38) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr38].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg9].pmp38cfg[4] == 1)) { + return CSR[pmpaddr38].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg9].pmp38cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr38].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg8].pmp38cfg[4] == 1)) { - return CSR[pmpaddr38].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr38].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg8].pmp38cfg[4] == 1)) { + return CSR[pmpaddr38].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg8].pmp38cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr38].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg8].pmp38cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr38].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr38].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr38].ADDR; } + } diff --git a/arch/csr/I/pmpaddr39.yaml b/arch/csr/I/pmpaddr39.yaml index 15f0ac692..f9966eaa9 100644 --- a/arch/csr/I/pmpaddr39.yaml +++ b/arch/csr/I/pmpaddr39.yaml @@ -4,73 +4,75 @@ -pmpaddr39: - long_name: PMP Address 39 - address: 0x3D7 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 39 - (or, if `pmp40cfg.A` == TOR, for PMP entry 40). - type(): | - if (NUM_PMP_ENTRIES > 39) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 39) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 39) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg9].pmp39cfg[4] == 1)) { - return CSR[pmpaddr39].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg9].pmp39cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr39].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr39 +long_name: PMP Address 39 +address: 0x3D7 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 39 + (or, if `pmp40cfg.A` == TOR, for PMP entry 40). + type(): | + if (NUM_PMP_ENTRIES > 39) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 39) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 39) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr39].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg9].pmp39cfg[4] == 1)) { + return CSR[pmpaddr39].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg9].pmp39cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr39].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg8].pmp39cfg[4] == 1)) { - return CSR[pmpaddr39].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr39].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg8].pmp39cfg[4] == 1)) { + return CSR[pmpaddr39].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg8].pmp39cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr39].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg8].pmp39cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr39].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr39].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr39].ADDR; } + } diff --git a/arch/csr/I/pmpaddr4.yaml b/arch/csr/I/pmpaddr4.yaml index 3e04fa08f..4ea909757 100644 --- a/arch/csr/I/pmpaddr4.yaml +++ b/arch/csr/I/pmpaddr4.yaml @@ -4,73 +4,75 @@ -pmpaddr4: - long_name: PMP Address 4 - address: 0x3B4 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 4 - (or, if `pmp5cfg.A` == TOR, for PMP entry 5). - type(): | - if (NUM_PMP_ENTRIES > 4) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 4) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 4) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg1].pmp4cfg[4] == 1)) { - return CSR[pmpaddr4].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg1].pmp4cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr4].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr4 +long_name: PMP Address 4 +address: 0x3B4 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 4 + (or, if `pmp5cfg.A` == TOR, for PMP entry 5). + type(): | + if (NUM_PMP_ENTRIES > 4) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 4) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 4) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr4].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg1].pmp4cfg[4] == 1)) { + return CSR[pmpaddr4].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg1].pmp4cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr4].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg0].pmp4cfg[4] == 1)) { - return CSR[pmpaddr4].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr4].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg0].pmp4cfg[4] == 1)) { + return CSR[pmpaddr4].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg0].pmp4cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr4].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg0].pmp4cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr4].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr4].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr4].ADDR; } + } diff --git a/arch/csr/I/pmpaddr40.yaml b/arch/csr/I/pmpaddr40.yaml index d065fb139..496d6a9b8 100644 --- a/arch/csr/I/pmpaddr40.yaml +++ b/arch/csr/I/pmpaddr40.yaml @@ -4,73 +4,75 @@ -pmpaddr40: - long_name: PMP Address 40 - address: 0x3D8 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 40 - (or, if `pmp41cfg.A` == TOR, for PMP entry 41). - type(): | - if (NUM_PMP_ENTRIES > 40) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 40) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 40) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg10].pmp40cfg[4] == 1)) { - return CSR[pmpaddr40].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg10].pmp40cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr40].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr40 +long_name: PMP Address 40 +address: 0x3D8 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 40 + (or, if `pmp41cfg.A` == TOR, for PMP entry 41). + type(): | + if (NUM_PMP_ENTRIES > 40) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 40) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 40) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr40].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg10].pmp40cfg[4] == 1)) { + return CSR[pmpaddr40].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg10].pmp40cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr40].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg10].pmp40cfg[4] == 1)) { - return CSR[pmpaddr40].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr40].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg10].pmp40cfg[4] == 1)) { + return CSR[pmpaddr40].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg10].pmp40cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr40].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg10].pmp40cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr40].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr40].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr40].ADDR; } + } diff --git a/arch/csr/I/pmpaddr41.yaml b/arch/csr/I/pmpaddr41.yaml index a32acf4f6..c187fa435 100644 --- a/arch/csr/I/pmpaddr41.yaml +++ b/arch/csr/I/pmpaddr41.yaml @@ -4,73 +4,75 @@ -pmpaddr41: - long_name: PMP Address 41 - address: 0x3D9 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 41 - (or, if `pmp42cfg.A` == TOR, for PMP entry 42). - type(): | - if (NUM_PMP_ENTRIES > 41) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 41) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 41) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg10].pmp41cfg[4] == 1)) { - return CSR[pmpaddr41].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg10].pmp41cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr41].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr41 +long_name: PMP Address 41 +address: 0x3D9 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 41 + (or, if `pmp42cfg.A` == TOR, for PMP entry 42). + type(): | + if (NUM_PMP_ENTRIES > 41) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 41) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 41) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr41].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg10].pmp41cfg[4] == 1)) { + return CSR[pmpaddr41].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg10].pmp41cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr41].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg10].pmp41cfg[4] == 1)) { - return CSR[pmpaddr41].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr41].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg10].pmp41cfg[4] == 1)) { + return CSR[pmpaddr41].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg10].pmp41cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr41].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg10].pmp41cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr41].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr41].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr41].ADDR; } + } diff --git a/arch/csr/I/pmpaddr42.yaml b/arch/csr/I/pmpaddr42.yaml index 08ff950cf..4daef7a3c 100644 --- a/arch/csr/I/pmpaddr42.yaml +++ b/arch/csr/I/pmpaddr42.yaml @@ -4,73 +4,75 @@ -pmpaddr42: - long_name: PMP Address 42 - address: 0x3DA - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 42 - (or, if `pmp43cfg.A` == TOR, for PMP entry 43). - type(): | - if (NUM_PMP_ENTRIES > 42) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 42) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 42) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg10].pmp42cfg[4] == 1)) { - return CSR[pmpaddr42].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg10].pmp42cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr42].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr42 +long_name: PMP Address 42 +address: 0x3DA +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 42 + (or, if `pmp43cfg.A` == TOR, for PMP entry 43). + type(): | + if (NUM_PMP_ENTRIES > 42) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 42) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 42) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr42].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg10].pmp42cfg[4] == 1)) { + return CSR[pmpaddr42].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg10].pmp42cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr42].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg10].pmp42cfg[4] == 1)) { - return CSR[pmpaddr42].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr42].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg10].pmp42cfg[4] == 1)) { + return CSR[pmpaddr42].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg10].pmp42cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr42].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg10].pmp42cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr42].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr42].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr42].ADDR; } + } diff --git a/arch/csr/I/pmpaddr43.yaml b/arch/csr/I/pmpaddr43.yaml index 3033b1f9f..e8dd8f949 100644 --- a/arch/csr/I/pmpaddr43.yaml +++ b/arch/csr/I/pmpaddr43.yaml @@ -4,73 +4,75 @@ -pmpaddr43: - long_name: PMP Address 43 - address: 0x3DB - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 43 - (or, if `pmp44cfg.A` == TOR, for PMP entry 44). - type(): | - if (NUM_PMP_ENTRIES > 43) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 43) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 43) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg10].pmp43cfg[4] == 1)) { - return CSR[pmpaddr43].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg10].pmp43cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr43].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr43 +long_name: PMP Address 43 +address: 0x3DB +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 43 + (or, if `pmp44cfg.A` == TOR, for PMP entry 44). + type(): | + if (NUM_PMP_ENTRIES > 43) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 43) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 43) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr43].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg10].pmp43cfg[4] == 1)) { + return CSR[pmpaddr43].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg10].pmp43cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr43].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg10].pmp43cfg[4] == 1)) { - return CSR[pmpaddr43].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr43].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg10].pmp43cfg[4] == 1)) { + return CSR[pmpaddr43].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg10].pmp43cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr43].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg10].pmp43cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr43].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr43].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr43].ADDR; } + } diff --git a/arch/csr/I/pmpaddr44.yaml b/arch/csr/I/pmpaddr44.yaml index 85b5c1bf8..1ccd84dfc 100644 --- a/arch/csr/I/pmpaddr44.yaml +++ b/arch/csr/I/pmpaddr44.yaml @@ -4,73 +4,75 @@ -pmpaddr44: - long_name: PMP Address 44 - address: 0x3DC - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 44 - (or, if `pmp45cfg.A` == TOR, for PMP entry 45). - type(): | - if (NUM_PMP_ENTRIES > 44) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 44) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 44) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg11].pmp44cfg[4] == 1)) { - return CSR[pmpaddr44].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg11].pmp44cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr44].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr44 +long_name: PMP Address 44 +address: 0x3DC +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 44 + (or, if `pmp45cfg.A` == TOR, for PMP entry 45). + type(): | + if (NUM_PMP_ENTRIES > 44) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 44) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 44) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr44].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg11].pmp44cfg[4] == 1)) { + return CSR[pmpaddr44].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg11].pmp44cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr44].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg10].pmp44cfg[4] == 1)) { - return CSR[pmpaddr44].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr44].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg10].pmp44cfg[4] == 1)) { + return CSR[pmpaddr44].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg10].pmp44cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr44].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg10].pmp44cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr44].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr44].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr44].ADDR; } + } diff --git a/arch/csr/I/pmpaddr45.yaml b/arch/csr/I/pmpaddr45.yaml index 916b87e2f..e600d8e97 100644 --- a/arch/csr/I/pmpaddr45.yaml +++ b/arch/csr/I/pmpaddr45.yaml @@ -4,73 +4,75 @@ -pmpaddr45: - long_name: PMP Address 45 - address: 0x3DD - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 45 - (or, if `pmp46cfg.A` == TOR, for PMP entry 46). - type(): | - if (NUM_PMP_ENTRIES > 45) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 45) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 45) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg11].pmp45cfg[4] == 1)) { - return CSR[pmpaddr45].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg11].pmp45cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr45].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr45 +long_name: PMP Address 45 +address: 0x3DD +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 45 + (or, if `pmp46cfg.A` == TOR, for PMP entry 46). + type(): | + if (NUM_PMP_ENTRIES > 45) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 45) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 45) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr45].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg11].pmp45cfg[4] == 1)) { + return CSR[pmpaddr45].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg11].pmp45cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr45].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg10].pmp45cfg[4] == 1)) { - return CSR[pmpaddr45].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr45].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg10].pmp45cfg[4] == 1)) { + return CSR[pmpaddr45].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg10].pmp45cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr45].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg10].pmp45cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr45].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr45].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr45].ADDR; } + } diff --git a/arch/csr/I/pmpaddr46.yaml b/arch/csr/I/pmpaddr46.yaml index 7bc21d2d7..9869421e0 100644 --- a/arch/csr/I/pmpaddr46.yaml +++ b/arch/csr/I/pmpaddr46.yaml @@ -4,73 +4,75 @@ -pmpaddr46: - long_name: PMP Address 46 - address: 0x3DE - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 46 - (or, if `pmp47cfg.A` == TOR, for PMP entry 47). - type(): | - if (NUM_PMP_ENTRIES > 46) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 46) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 46) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg11].pmp46cfg[4] == 1)) { - return CSR[pmpaddr46].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg11].pmp46cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr46].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr46 +long_name: PMP Address 46 +address: 0x3DE +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 46 + (or, if `pmp47cfg.A` == TOR, for PMP entry 47). + type(): | + if (NUM_PMP_ENTRIES > 46) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 46) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 46) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr46].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg11].pmp46cfg[4] == 1)) { + return CSR[pmpaddr46].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg11].pmp46cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr46].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg10].pmp46cfg[4] == 1)) { - return CSR[pmpaddr46].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr46].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg10].pmp46cfg[4] == 1)) { + return CSR[pmpaddr46].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg10].pmp46cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr46].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg10].pmp46cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr46].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr46].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr46].ADDR; } + } diff --git a/arch/csr/I/pmpaddr47.yaml b/arch/csr/I/pmpaddr47.yaml index dd843a70c..7f5b867a4 100644 --- a/arch/csr/I/pmpaddr47.yaml +++ b/arch/csr/I/pmpaddr47.yaml @@ -4,73 +4,75 @@ -pmpaddr47: - long_name: PMP Address 47 - address: 0x3DF - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 47 - (or, if `pmp48cfg.A` == TOR, for PMP entry 48). - type(): | - if (NUM_PMP_ENTRIES > 47) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 47) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 47) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg11].pmp47cfg[4] == 1)) { - return CSR[pmpaddr47].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg11].pmp47cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr47].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr47 +long_name: PMP Address 47 +address: 0x3DF +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 47 + (or, if `pmp48cfg.A` == TOR, for PMP entry 48). + type(): | + if (NUM_PMP_ENTRIES > 47) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 47) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 47) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr47].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg11].pmp47cfg[4] == 1)) { + return CSR[pmpaddr47].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg11].pmp47cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr47].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg10].pmp47cfg[4] == 1)) { - return CSR[pmpaddr47].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr47].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg10].pmp47cfg[4] == 1)) { + return CSR[pmpaddr47].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg10].pmp47cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr47].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg10].pmp47cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr47].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr47].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr47].ADDR; } + } diff --git a/arch/csr/I/pmpaddr48.yaml b/arch/csr/I/pmpaddr48.yaml index ace42b7db..739549f6c 100644 --- a/arch/csr/I/pmpaddr48.yaml +++ b/arch/csr/I/pmpaddr48.yaml @@ -4,73 +4,75 @@ -pmpaddr48: - long_name: PMP Address 48 - address: 0x3E0 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 48 - (or, if `pmp49cfg.A` == TOR, for PMP entry 49). - type(): | - if (NUM_PMP_ENTRIES > 48) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 48) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 48) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg12].pmp48cfg[4] == 1)) { - return CSR[pmpaddr48].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg12].pmp48cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr48].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr48 +long_name: PMP Address 48 +address: 0x3E0 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 48 + (or, if `pmp49cfg.A` == TOR, for PMP entry 49). + type(): | + if (NUM_PMP_ENTRIES > 48) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 48) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 48) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr48].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg12].pmp48cfg[4] == 1)) { + return CSR[pmpaddr48].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg12].pmp48cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr48].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg12].pmp48cfg[4] == 1)) { - return CSR[pmpaddr48].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr48].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg12].pmp48cfg[4] == 1)) { + return CSR[pmpaddr48].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg12].pmp48cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr48].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg12].pmp48cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr48].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr48].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr48].ADDR; } + } diff --git a/arch/csr/I/pmpaddr49.yaml b/arch/csr/I/pmpaddr49.yaml index d74fdebc9..e14ed4ff6 100644 --- a/arch/csr/I/pmpaddr49.yaml +++ b/arch/csr/I/pmpaddr49.yaml @@ -4,73 +4,75 @@ -pmpaddr49: - long_name: PMP Address 49 - address: 0x3E1 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 49 - (or, if `pmp50cfg.A` == TOR, for PMP entry 50). - type(): | - if (NUM_PMP_ENTRIES > 49) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 49) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 49) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg12].pmp49cfg[4] == 1)) { - return CSR[pmpaddr49].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg12].pmp49cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr49].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr49 +long_name: PMP Address 49 +address: 0x3E1 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 49 + (or, if `pmp50cfg.A` == TOR, for PMP entry 50). + type(): | + if (NUM_PMP_ENTRIES > 49) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 49) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 49) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr49].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg12].pmp49cfg[4] == 1)) { + return CSR[pmpaddr49].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg12].pmp49cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr49].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg12].pmp49cfg[4] == 1)) { - return CSR[pmpaddr49].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr49].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg12].pmp49cfg[4] == 1)) { + return CSR[pmpaddr49].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg12].pmp49cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr49].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg12].pmp49cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr49].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr49].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr49].ADDR; } + } diff --git a/arch/csr/I/pmpaddr5.yaml b/arch/csr/I/pmpaddr5.yaml index b3cbbebe5..998712e5c 100644 --- a/arch/csr/I/pmpaddr5.yaml +++ b/arch/csr/I/pmpaddr5.yaml @@ -4,73 +4,75 @@ -pmpaddr5: - long_name: PMP Address 5 - address: 0x3B5 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 5 - (or, if `pmp6cfg.A` == TOR, for PMP entry 6). - type(): | - if (NUM_PMP_ENTRIES > 5) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 5) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 5) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg1].pmp5cfg[4] == 1)) { - return CSR[pmpaddr5].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg1].pmp5cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr5].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr5 +long_name: PMP Address 5 +address: 0x3B5 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 5 + (or, if `pmp6cfg.A` == TOR, for PMP entry 6). + type(): | + if (NUM_PMP_ENTRIES > 5) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 5) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 5) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr5].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg1].pmp5cfg[4] == 1)) { + return CSR[pmpaddr5].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg1].pmp5cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr5].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg0].pmp5cfg[4] == 1)) { - return CSR[pmpaddr5].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr5].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg0].pmp5cfg[4] == 1)) { + return CSR[pmpaddr5].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg0].pmp5cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr5].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg0].pmp5cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr5].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr5].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr5].ADDR; } + } diff --git a/arch/csr/I/pmpaddr50.yaml b/arch/csr/I/pmpaddr50.yaml index 649ad63dc..6226177fc 100644 --- a/arch/csr/I/pmpaddr50.yaml +++ b/arch/csr/I/pmpaddr50.yaml @@ -4,73 +4,75 @@ -pmpaddr50: - long_name: PMP Address 50 - address: 0x3E2 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 50 - (or, if `pmp51cfg.A` == TOR, for PMP entry 51). - type(): | - if (NUM_PMP_ENTRIES > 50) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 50) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 50) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg12].pmp50cfg[4] == 1)) { - return CSR[pmpaddr50].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg12].pmp50cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr50].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr50 +long_name: PMP Address 50 +address: 0x3E2 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 50 + (or, if `pmp51cfg.A` == TOR, for PMP entry 51). + type(): | + if (NUM_PMP_ENTRIES > 50) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 50) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 50) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr50].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg12].pmp50cfg[4] == 1)) { + return CSR[pmpaddr50].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg12].pmp50cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr50].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg12].pmp50cfg[4] == 1)) { - return CSR[pmpaddr50].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr50].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg12].pmp50cfg[4] == 1)) { + return CSR[pmpaddr50].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg12].pmp50cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr50].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg12].pmp50cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr50].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr50].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr50].ADDR; } + } diff --git a/arch/csr/I/pmpaddr51.yaml b/arch/csr/I/pmpaddr51.yaml index 047fa2a56..45461b001 100644 --- a/arch/csr/I/pmpaddr51.yaml +++ b/arch/csr/I/pmpaddr51.yaml @@ -4,73 +4,75 @@ -pmpaddr51: - long_name: PMP Address 51 - address: 0x3E3 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 51 - (or, if `pmp52cfg.A` == TOR, for PMP entry 52). - type(): | - if (NUM_PMP_ENTRIES > 51) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 51) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 51) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg12].pmp51cfg[4] == 1)) { - return CSR[pmpaddr51].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg12].pmp51cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr51].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr51 +long_name: PMP Address 51 +address: 0x3E3 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 51 + (or, if `pmp52cfg.A` == TOR, for PMP entry 52). + type(): | + if (NUM_PMP_ENTRIES > 51) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 51) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 51) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr51].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg12].pmp51cfg[4] == 1)) { + return CSR[pmpaddr51].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg12].pmp51cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr51].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg12].pmp51cfg[4] == 1)) { - return CSR[pmpaddr51].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr51].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg12].pmp51cfg[4] == 1)) { + return CSR[pmpaddr51].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg12].pmp51cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr51].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg12].pmp51cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr51].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr51].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr51].ADDR; } + } diff --git a/arch/csr/I/pmpaddr52.yaml b/arch/csr/I/pmpaddr52.yaml index bb9a659e5..936908255 100644 --- a/arch/csr/I/pmpaddr52.yaml +++ b/arch/csr/I/pmpaddr52.yaml @@ -4,73 +4,75 @@ -pmpaddr52: - long_name: PMP Address 52 - address: 0x3E4 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 52 - (or, if `pmp53cfg.A` == TOR, for PMP entry 53). - type(): | - if (NUM_PMP_ENTRIES > 52) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 52) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 52) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg13].pmp52cfg[4] == 1)) { - return CSR[pmpaddr52].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg13].pmp52cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr52].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr52 +long_name: PMP Address 52 +address: 0x3E4 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 52 + (or, if `pmp53cfg.A` == TOR, for PMP entry 53). + type(): | + if (NUM_PMP_ENTRIES > 52) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 52) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 52) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr52].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg13].pmp52cfg[4] == 1)) { + return CSR[pmpaddr52].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg13].pmp52cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr52].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg12].pmp52cfg[4] == 1)) { - return CSR[pmpaddr52].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr52].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg12].pmp52cfg[4] == 1)) { + return CSR[pmpaddr52].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg12].pmp52cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr52].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg12].pmp52cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr52].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr52].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr52].ADDR; } + } diff --git a/arch/csr/I/pmpaddr53.yaml b/arch/csr/I/pmpaddr53.yaml index f9fd91c6d..8e6e625ec 100644 --- a/arch/csr/I/pmpaddr53.yaml +++ b/arch/csr/I/pmpaddr53.yaml @@ -4,73 +4,75 @@ -pmpaddr53: - long_name: PMP Address 53 - address: 0x3E5 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 53 - (or, if `pmp54cfg.A` == TOR, for PMP entry 54). - type(): | - if (NUM_PMP_ENTRIES > 53) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 53) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 53) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg13].pmp53cfg[4] == 1)) { - return CSR[pmpaddr53].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg13].pmp53cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr53].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr53 +long_name: PMP Address 53 +address: 0x3E5 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 53 + (or, if `pmp54cfg.A` == TOR, for PMP entry 54). + type(): | + if (NUM_PMP_ENTRIES > 53) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 53) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 53) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr53].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg13].pmp53cfg[4] == 1)) { + return CSR[pmpaddr53].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg13].pmp53cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr53].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg12].pmp53cfg[4] == 1)) { - return CSR[pmpaddr53].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr53].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg12].pmp53cfg[4] == 1)) { + return CSR[pmpaddr53].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg12].pmp53cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr53].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg12].pmp53cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr53].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr53].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr53].ADDR; } + } diff --git a/arch/csr/I/pmpaddr54.yaml b/arch/csr/I/pmpaddr54.yaml index 864d0155d..be5082f31 100644 --- a/arch/csr/I/pmpaddr54.yaml +++ b/arch/csr/I/pmpaddr54.yaml @@ -4,73 +4,75 @@ -pmpaddr54: - long_name: PMP Address 54 - address: 0x3E6 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 54 - (or, if `pmp55cfg.A` == TOR, for PMP entry 55). - type(): | - if (NUM_PMP_ENTRIES > 54) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 54) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 54) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg13].pmp54cfg[4] == 1)) { - return CSR[pmpaddr54].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg13].pmp54cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr54].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr54 +long_name: PMP Address 54 +address: 0x3E6 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 54 + (or, if `pmp55cfg.A` == TOR, for PMP entry 55). + type(): | + if (NUM_PMP_ENTRIES > 54) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 54) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 54) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr54].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg13].pmp54cfg[4] == 1)) { + return CSR[pmpaddr54].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg13].pmp54cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr54].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg12].pmp54cfg[4] == 1)) { - return CSR[pmpaddr54].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr54].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg12].pmp54cfg[4] == 1)) { + return CSR[pmpaddr54].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg12].pmp54cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr54].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg12].pmp54cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr54].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr54].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr54].ADDR; } + } diff --git a/arch/csr/I/pmpaddr55.yaml b/arch/csr/I/pmpaddr55.yaml index ebfc4ed9c..0602b076f 100644 --- a/arch/csr/I/pmpaddr55.yaml +++ b/arch/csr/I/pmpaddr55.yaml @@ -4,73 +4,75 @@ -pmpaddr55: - long_name: PMP Address 55 - address: 0x3E7 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 55 - (or, if `pmp56cfg.A` == TOR, for PMP entry 56). - type(): | - if (NUM_PMP_ENTRIES > 55) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 55) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 55) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg13].pmp55cfg[4] == 1)) { - return CSR[pmpaddr55].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg13].pmp55cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr55].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr55 +long_name: PMP Address 55 +address: 0x3E7 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 55 + (or, if `pmp56cfg.A` == TOR, for PMP entry 56). + type(): | + if (NUM_PMP_ENTRIES > 55) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 55) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 55) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr55].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg13].pmp55cfg[4] == 1)) { + return CSR[pmpaddr55].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg13].pmp55cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr55].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg12].pmp55cfg[4] == 1)) { - return CSR[pmpaddr55].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr55].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg12].pmp55cfg[4] == 1)) { + return CSR[pmpaddr55].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg12].pmp55cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr55].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg12].pmp55cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr55].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr55].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr55].ADDR; } + } diff --git a/arch/csr/I/pmpaddr56.yaml b/arch/csr/I/pmpaddr56.yaml index 9f6aa9093..0a2be33f0 100644 --- a/arch/csr/I/pmpaddr56.yaml +++ b/arch/csr/I/pmpaddr56.yaml @@ -4,73 +4,75 @@ -pmpaddr56: - long_name: PMP Address 56 - address: 0x3E8 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 56 - (or, if `pmp57cfg.A` == TOR, for PMP entry 57). - type(): | - if (NUM_PMP_ENTRIES > 56) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 56) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 56) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg14].pmp56cfg[4] == 1)) { - return CSR[pmpaddr56].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg14].pmp56cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr56].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr56 +long_name: PMP Address 56 +address: 0x3E8 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 56 + (or, if `pmp57cfg.A` == TOR, for PMP entry 57). + type(): | + if (NUM_PMP_ENTRIES > 56) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 56) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 56) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr56].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg14].pmp56cfg[4] == 1)) { + return CSR[pmpaddr56].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg14].pmp56cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr56].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg14].pmp56cfg[4] == 1)) { - return CSR[pmpaddr56].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr56].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg14].pmp56cfg[4] == 1)) { + return CSR[pmpaddr56].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg14].pmp56cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr56].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg14].pmp56cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr56].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr56].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr56].ADDR; } + } diff --git a/arch/csr/I/pmpaddr57.yaml b/arch/csr/I/pmpaddr57.yaml index 68ce2873e..1896ef4c6 100644 --- a/arch/csr/I/pmpaddr57.yaml +++ b/arch/csr/I/pmpaddr57.yaml @@ -4,73 +4,75 @@ -pmpaddr57: - long_name: PMP Address 57 - address: 0x3E9 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 57 - (or, if `pmp58cfg.A` == TOR, for PMP entry 58). - type(): | - if (NUM_PMP_ENTRIES > 57) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 57) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 57) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg14].pmp57cfg[4] == 1)) { - return CSR[pmpaddr57].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg14].pmp57cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr57].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr57 +long_name: PMP Address 57 +address: 0x3E9 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 57 + (or, if `pmp58cfg.A` == TOR, for PMP entry 58). + type(): | + if (NUM_PMP_ENTRIES > 57) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 57) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 57) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr57].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg14].pmp57cfg[4] == 1)) { + return CSR[pmpaddr57].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg14].pmp57cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr57].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg14].pmp57cfg[4] == 1)) { - return CSR[pmpaddr57].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr57].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg14].pmp57cfg[4] == 1)) { + return CSR[pmpaddr57].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg14].pmp57cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr57].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg14].pmp57cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr57].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr57].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr57].ADDR; } + } diff --git a/arch/csr/I/pmpaddr58.yaml b/arch/csr/I/pmpaddr58.yaml index 4c41b889a..78838af7d 100644 --- a/arch/csr/I/pmpaddr58.yaml +++ b/arch/csr/I/pmpaddr58.yaml @@ -4,73 +4,75 @@ -pmpaddr58: - long_name: PMP Address 58 - address: 0x3EA - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 58 - (or, if `pmp59cfg.A` == TOR, for PMP entry 59). - type(): | - if (NUM_PMP_ENTRIES > 58) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 58) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 58) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg14].pmp58cfg[4] == 1)) { - return CSR[pmpaddr58].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg14].pmp58cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr58].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr58 +long_name: PMP Address 58 +address: 0x3EA +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 58 + (or, if `pmp59cfg.A` == TOR, for PMP entry 59). + type(): | + if (NUM_PMP_ENTRIES > 58) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 58) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 58) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr58].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg14].pmp58cfg[4] == 1)) { + return CSR[pmpaddr58].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg14].pmp58cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr58].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg14].pmp58cfg[4] == 1)) { - return CSR[pmpaddr58].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr58].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg14].pmp58cfg[4] == 1)) { + return CSR[pmpaddr58].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg14].pmp58cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr58].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg14].pmp58cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr58].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr58].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr58].ADDR; } + } diff --git a/arch/csr/I/pmpaddr59.yaml b/arch/csr/I/pmpaddr59.yaml index 9ca64d055..8494a9ee5 100644 --- a/arch/csr/I/pmpaddr59.yaml +++ b/arch/csr/I/pmpaddr59.yaml @@ -4,73 +4,75 @@ -pmpaddr59: - long_name: PMP Address 59 - address: 0x3EB - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 59 - (or, if `pmp60cfg.A` == TOR, for PMP entry 60). - type(): | - if (NUM_PMP_ENTRIES > 59) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 59) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 59) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg14].pmp59cfg[4] == 1)) { - return CSR[pmpaddr59].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg14].pmp59cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr59].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr59 +long_name: PMP Address 59 +address: 0x3EB +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 59 + (or, if `pmp60cfg.A` == TOR, for PMP entry 60). + type(): | + if (NUM_PMP_ENTRIES > 59) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 59) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 59) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr59].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg14].pmp59cfg[4] == 1)) { + return CSR[pmpaddr59].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg14].pmp59cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr59].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg14].pmp59cfg[4] == 1)) { - return CSR[pmpaddr59].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr59].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg14].pmp59cfg[4] == 1)) { + return CSR[pmpaddr59].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg14].pmp59cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr59].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg14].pmp59cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr59].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr59].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr59].ADDR; } + } diff --git a/arch/csr/I/pmpaddr6.yaml b/arch/csr/I/pmpaddr6.yaml index dc3c12f29..eba823575 100644 --- a/arch/csr/I/pmpaddr6.yaml +++ b/arch/csr/I/pmpaddr6.yaml @@ -4,73 +4,75 @@ -pmpaddr6: - long_name: PMP Address 6 - address: 0x3B6 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 6 - (or, if `pmp7cfg.A` == TOR, for PMP entry 7). - type(): | - if (NUM_PMP_ENTRIES > 6) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 6) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 6) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg1].pmp6cfg[4] == 1)) { - return CSR[pmpaddr6].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg1].pmp6cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr6].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr6 +long_name: PMP Address 6 +address: 0x3B6 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 6 + (or, if `pmp7cfg.A` == TOR, for PMP entry 7). + type(): | + if (NUM_PMP_ENTRIES > 6) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 6) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 6) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr6].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg1].pmp6cfg[4] == 1)) { + return CSR[pmpaddr6].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg1].pmp6cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr6].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg0].pmp6cfg[4] == 1)) { - return CSR[pmpaddr6].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr6].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg0].pmp6cfg[4] == 1)) { + return CSR[pmpaddr6].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg0].pmp6cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr6].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg0].pmp6cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr6].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr6].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr6].ADDR; } + } diff --git a/arch/csr/I/pmpaddr60.yaml b/arch/csr/I/pmpaddr60.yaml index eb3153bbf..b33f867e9 100644 --- a/arch/csr/I/pmpaddr60.yaml +++ b/arch/csr/I/pmpaddr60.yaml @@ -4,73 +4,75 @@ -pmpaddr60: - long_name: PMP Address 60 - address: 0x3EC - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 60 - (or, if `pmp61cfg.A` == TOR, for PMP entry 61). - type(): | - if (NUM_PMP_ENTRIES > 60) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 60) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 60) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg15].pmp60cfg[4] == 1)) { - return CSR[pmpaddr60].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg15].pmp60cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr60].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr60 +long_name: PMP Address 60 +address: 0x3EC +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 60 + (or, if `pmp61cfg.A` == TOR, for PMP entry 61). + type(): | + if (NUM_PMP_ENTRIES > 60) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 60) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 60) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr60].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg15].pmp60cfg[4] == 1)) { + return CSR[pmpaddr60].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg15].pmp60cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr60].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg14].pmp60cfg[4] == 1)) { - return CSR[pmpaddr60].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr60].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg14].pmp60cfg[4] == 1)) { + return CSR[pmpaddr60].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg14].pmp60cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr60].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg14].pmp60cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr60].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr60].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr60].ADDR; } + } diff --git a/arch/csr/I/pmpaddr61.yaml b/arch/csr/I/pmpaddr61.yaml index 3869c1949..55c4244d9 100644 --- a/arch/csr/I/pmpaddr61.yaml +++ b/arch/csr/I/pmpaddr61.yaml @@ -4,73 +4,75 @@ -pmpaddr61: - long_name: PMP Address 61 - address: 0x3ED - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 61 - (or, if `pmp62cfg.A` == TOR, for PMP entry 62). - type(): | - if (NUM_PMP_ENTRIES > 61) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 61) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 61) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg15].pmp61cfg[4] == 1)) { - return CSR[pmpaddr61].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg15].pmp61cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr61].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr61 +long_name: PMP Address 61 +address: 0x3ED +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 61 + (or, if `pmp62cfg.A` == TOR, for PMP entry 62). + type(): | + if (NUM_PMP_ENTRIES > 61) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 61) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 61) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr61].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg15].pmp61cfg[4] == 1)) { + return CSR[pmpaddr61].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg15].pmp61cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr61].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg14].pmp61cfg[4] == 1)) { - return CSR[pmpaddr61].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr61].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg14].pmp61cfg[4] == 1)) { + return CSR[pmpaddr61].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg14].pmp61cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr61].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg14].pmp61cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr61].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr61].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr61].ADDR; } + } diff --git a/arch/csr/I/pmpaddr62.yaml b/arch/csr/I/pmpaddr62.yaml index 1564bc57f..ba3ffcece 100644 --- a/arch/csr/I/pmpaddr62.yaml +++ b/arch/csr/I/pmpaddr62.yaml @@ -4,73 +4,75 @@ -pmpaddr62: - long_name: PMP Address 62 - address: 0x3EE - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 62 - (or, if `pmp63cfg.A` == TOR, for PMP entry 63). - type(): | - if (NUM_PMP_ENTRIES > 62) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 62) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 62) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg15].pmp62cfg[4] == 1)) { - return CSR[pmpaddr62].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg15].pmp62cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr62].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr62 +long_name: PMP Address 62 +address: 0x3EE +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 62 + (or, if `pmp63cfg.A` == TOR, for PMP entry 63). + type(): | + if (NUM_PMP_ENTRIES > 62) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 62) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 62) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr62].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg15].pmp62cfg[4] == 1)) { + return CSR[pmpaddr62].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg15].pmp62cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr62].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg14].pmp62cfg[4] == 1)) { - return CSR[pmpaddr62].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr62].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg14].pmp62cfg[4] == 1)) { + return CSR[pmpaddr62].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg14].pmp62cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr62].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg14].pmp62cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr62].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr62].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr62].ADDR; } + } diff --git a/arch/csr/I/pmpaddr63.yaml b/arch/csr/I/pmpaddr63.yaml index 117924921..40cf7a6e2 100644 --- a/arch/csr/I/pmpaddr63.yaml +++ b/arch/csr/I/pmpaddr63.yaml @@ -4,73 +4,75 @@ -pmpaddr63: - long_name: PMP Address 63 - address: 0x3EF - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 63 - (or, if `pmp64cfg.A` == TOR, for PMP entry 64). - type(): | - if (NUM_PMP_ENTRIES > 63) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 63) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 63) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg15].pmp63cfg[4] == 1)) { - return CSR[pmpaddr63].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg15].pmp63cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr63].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr63 +long_name: PMP Address 63 +address: 0x3EF +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 63 + (or, if `pmp64cfg.A` == TOR, for PMP entry 64). + type(): | + if (NUM_PMP_ENTRIES > 63) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 63) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 63) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr63].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg15].pmp63cfg[4] == 1)) { + return CSR[pmpaddr63].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg15].pmp63cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr63].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg14].pmp63cfg[4] == 1)) { - return CSR[pmpaddr63].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr63].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg14].pmp63cfg[4] == 1)) { + return CSR[pmpaddr63].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg14].pmp63cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr63].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg14].pmp63cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr63].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr63].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr63].ADDR; } + } diff --git a/arch/csr/I/pmpaddr7.yaml b/arch/csr/I/pmpaddr7.yaml index 209895ad2..105d6cbf2 100644 --- a/arch/csr/I/pmpaddr7.yaml +++ b/arch/csr/I/pmpaddr7.yaml @@ -4,73 +4,75 @@ -pmpaddr7: - long_name: PMP Address 7 - address: 0x3B7 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 7 - (or, if `pmp8cfg.A` == TOR, for PMP entry 8). - type(): | - if (NUM_PMP_ENTRIES > 7) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 7) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 7) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg1].pmp7cfg[4] == 1)) { - return CSR[pmpaddr7].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg1].pmp7cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr7].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr7 +long_name: PMP Address 7 +address: 0x3B7 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 7 + (or, if `pmp8cfg.A` == TOR, for PMP entry 8). + type(): | + if (NUM_PMP_ENTRIES > 7) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 7) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 7) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr7].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg1].pmp7cfg[4] == 1)) { + return CSR[pmpaddr7].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg1].pmp7cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr7].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg0].pmp7cfg[4] == 1)) { - return CSR[pmpaddr7].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr7].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg0].pmp7cfg[4] == 1)) { + return CSR[pmpaddr7].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg0].pmp7cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr7].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg0].pmp7cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr7].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr7].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr7].ADDR; } + } diff --git a/arch/csr/I/pmpaddr8.yaml b/arch/csr/I/pmpaddr8.yaml index 2ebaf11a5..355789fcb 100644 --- a/arch/csr/I/pmpaddr8.yaml +++ b/arch/csr/I/pmpaddr8.yaml @@ -4,73 +4,75 @@ -pmpaddr8: - long_name: PMP Address 8 - address: 0x3B8 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 8 - (or, if `pmp9cfg.A` == TOR, for PMP entry 9). - type(): | - if (NUM_PMP_ENTRIES > 8) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 8) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 8) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg2].pmp8cfg[4] == 1)) { - return CSR[pmpaddr8].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg2].pmp8cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr8].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr8 +long_name: PMP Address 8 +address: 0x3B8 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 8 + (or, if `pmp9cfg.A` == TOR, for PMP entry 9). + type(): | + if (NUM_PMP_ENTRIES > 8) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 8) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 8) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr8].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg2].pmp8cfg[4] == 1)) { + return CSR[pmpaddr8].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg2].pmp8cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr8].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg2].pmp8cfg[4] == 1)) { - return CSR[pmpaddr8].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr8].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg2].pmp8cfg[4] == 1)) { + return CSR[pmpaddr8].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg2].pmp8cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr8].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg2].pmp8cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr8].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr8].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr8].ADDR; } + } diff --git a/arch/csr/I/pmpaddr9.yaml b/arch/csr/I/pmpaddr9.yaml index 51014c287..827cb70d2 100644 --- a/arch/csr/I/pmpaddr9.yaml +++ b/arch/csr/I/pmpaddr9.yaml @@ -4,73 +4,75 @@ -pmpaddr9: - long_name: PMP Address 9 - address: 0x3B9 - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 9 - (or, if `pmp10cfg.A` == TOR, for PMP entry 10). - type(): | - if (NUM_PMP_ENTRIES > 9) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 9) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > 9) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg2].pmp9cfg[4] == 1)) { - return CSR[pmpaddr9].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg2].pmp9cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr9].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr9 +long_name: PMP Address 9 +address: 0x3B9 +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry 9 + (or, if `pmp10cfg.A` == TOR, for PMP entry 10). + type(): | + if (NUM_PMP_ENTRIES > 9) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 9) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > 9) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr9].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg2].pmp9cfg[4] == 1)) { + return CSR[pmpaddr9].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg2].pmp9cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr9].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg2].pmp9cfg[4] == 1)) { - return CSR[pmpaddr9].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr9].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg2].pmp9cfg[4] == 1)) { + return CSR[pmpaddr9].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg2].pmp9cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr9].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg2].pmp9cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr9].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr9].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr9].ADDR; } + } diff --git a/arch/csr/I/pmpaddrN.layout b/arch/csr/I/pmpaddrN.layout index 31fbfc1e0..d42a4cb5c 100644 --- a/arch/csr/I/pmpaddrN.layout +++ b/arch/csr/I/pmpaddrN.layout @@ -6,73 +6,75 @@ pmpcfg_num_64 = (pmpaddr_num / 8)*2 -%> -pmpaddr<%= pmpaddr_num %>: - long_name: PMP Address <%= pmpaddr_num %> - address: 0x<%= (0x3B0 + pmpaddr_num).to_s(16).upcase %> - priv_mode: M - length: MXLEN - description: PMP entry address - definedBy: Smpmp - fields: - ADDR: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry <%= pmpaddr_num %> - (or, if `pmp<%= pmpaddr_num+1 %>cfg.A` == TOR, for PMP entry <%= pmpaddr_num + 1 %>). - type(): | - if (NUM_PMP_ENTRIES > <%= pmpaddr_num %>) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > <%= pmpaddr_num %>) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (NUM_PMP_ENTRIES > <%= pmpaddr_num %>) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.ADDR; - } - sw_read(): | - # when the mode is NAPOT and PMP_GRANULARITY >= 16, - # bits (PMP_GRANULARITY-4):0 must read as ones - if (XLEN == 32) { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg<%= pmpcfg_num_32 %>].pmp<%= pmpaddr_num %>cfg[4] == 1)) { - return CSR[pmpaddr<%= pmpaddr_num %>].ADDR | {PMP_GRANULARITY-3{1'b1}}; - - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg<%= pmpcfg_num_32 %>].pmp<%= pmpaddr_num %>cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr<%= pmpaddr_num %>].ADDR & ~mask; - - # no modifications needed +$schema: csr_schema.json# +kind: csr +name: pmpaddr<%= pmpaddr_num %> +long_name: PMP Address <%= pmpaddr_num %> +address: 0x<%= (0x3B0 + pmpaddr_num).to_s(16).upcase %> +priv_mode: M +length: MXLEN +description: PMP entry address +definedBy: Smpmp +fields: + ADDR: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Bits PHYS_ADDR_WIDTH-1:2 of the address specifier for PMP entry <%= pmpaddr_num %> + (or, if `pmp<%= pmpaddr_num+1 %>cfg.A` == TOR, for PMP entry <%= pmpaddr_num + 1 %>). + type(): | + if (NUM_PMP_ENTRIES > <%= pmpaddr_num %>) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > <%= pmpaddr_num %>) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (csr_value.ADDR >= (PHYS_ADDR_WIDTH >> 2)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (NUM_PMP_ENTRIES > <%= pmpaddr_num %>) { + return UNDEFINED_LEGAL_DETERMINISTIC; } else { - return CSR[pmpaddr<%= pmpaddr_num %>].ADDR; + return csr_value.ADDR; } +sw_read(): | + # when the mode is NAPOT and PMP_GRANULARITY >= 16, + # bits (PMP_GRANULARITY-4):0 must read as ones + if (XLEN == 32) { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg<%= pmpcfg_num_32 %>].pmp<%= pmpaddr_num %>cfg[4] == 1)) { + return CSR[pmpaddr<%= pmpaddr_num %>].ADDR | {PMP_GRANULARITY-3{1'b1}}; + + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg<%= pmpcfg_num_32 %>].pmp<%= pmpaddr_num %>cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr<%= pmpaddr_num %>].ADDR & ~mask; + + # no modifications needed } else { - if ((PMP_GRANULARITY >= 16) && - (CSR[pmpcfg<%= pmpcfg_num_64 %>].pmp<%= pmpaddr_num %>cfg[4] == 1)) { - return CSR[pmpaddr<%= pmpaddr_num %>].ADDR | {PMP_GRANULARITY-3{1'b1}}; + return CSR[pmpaddr<%= pmpaddr_num %>].ADDR; + } + } else { + if ((PMP_GRANULARITY >= 16) && + (CSR[pmpcfg<%= pmpcfg_num_64 %>].pmp<%= pmpaddr_num %>cfg[4] == 1)) { + return CSR[pmpaddr<%= pmpaddr_num %>].ADDR | {PMP_GRANULARITY-3{1'b1}}; - # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, - # bits (PMP_GRANULARITY-3):0 must read as zeros - } else if ((PMP_GRANULARITY >= 8) && - (CSR[pmpcfg<%= pmpcfg_num_64 %>].pmp<%= pmpaddr_num %>cfg[4] == 0)) { - Bits mask = {PMP_GRANULARITY-2{1'b1}}; - return CSR[pmpaddr<%= pmpaddr_num %>].ADDR & ~mask; + # when the mode is OFF or TOR and PMP_GRANULARITY >= 8, + # bits (PMP_GRANULARITY-3):0 must read as zeros + } else if ((PMP_GRANULARITY >= 8) && + (CSR[pmpcfg<%= pmpcfg_num_64 %>].pmp<%= pmpaddr_num %>cfg[4] == 0)) { + Bits mask = {PMP_GRANULARITY-2{1'b1}}; + return CSR[pmpaddr<%= pmpaddr_num %>].ADDR & ~mask; - # no modifications needed - } else { - return CSR[pmpaddr<%= pmpaddr_num %>].ADDR; - } + # no modifications needed + } else { + return CSR[pmpaddr<%= pmpaddr_num %>].ADDR; } + } diff --git a/arch/csr/I/pmpcfg0.yaml b/arch/csr/I/pmpcfg0.yaml index 2c9ff29c8..b1a599b02 100644 --- a/arch/csr/I/pmpcfg0.yaml +++ b/arch/csr/I/pmpcfg0.yaml @@ -4,511 +4,513 @@ -pmpcfg0: - long_name: PMP Configuration Register 0 - address: 0x3A0 - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp0cfg: - location: 7-0 - description: | - *PMP configuration for entry 0* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). +$schema: csr_schema.json# +kind: csr +name: pmpcfg0 +long_name: PMP Configuration Register 0 +address: 0x3A0 +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp0cfg: + location: 7-0 + description: | + *PMP configuration for entry 0* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 0) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 0) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg0].pmp0cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp0cfg & 0x1) == 0) && ((csr_value.pmp0cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp0cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp0cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 0) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 0) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg0].pmp0cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp0cfg & 0x1) == 0) && ((csr_value.pmp0cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp0cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp0cfg; } } - # fall through: keep old value - return CSR[pmpcfg0].pmp0cfg; - pmp1cfg: - location: 15-8 - description: | - *PMP configuration for entry 1* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg0].pmp0cfg; + pmp1cfg: + location: 15-8 + description: | + *PMP configuration for entry 1* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 1) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 1) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg0].pmp1cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp1cfg & 0x1) == 0) && ((csr_value.pmp1cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp1cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp1cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 1) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 1) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg0].pmp1cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp1cfg & 0x1) == 0) && ((csr_value.pmp1cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp1cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp1cfg; } } - # fall through: keep old value - return CSR[pmpcfg0].pmp1cfg; - pmp2cfg: - location: 23-16 - description: | - *PMP configuration for entry 2* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg0].pmp1cfg; + pmp2cfg: + location: 23-16 + description: | + *PMP configuration for entry 2* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 2) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 2) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg0].pmp2cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp2cfg & 0x1) == 0) && ((csr_value.pmp2cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp2cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp2cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 2) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 2) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg0].pmp2cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp2cfg & 0x1) == 0) && ((csr_value.pmp2cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp2cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp2cfg; } } - # fall through: keep old value - return CSR[pmpcfg0].pmp2cfg; - pmp3cfg: - location: 31-24 - description: | - *PMP configuration for entry 3* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg0].pmp2cfg; + pmp3cfg: + location: 31-24 + description: | + *PMP configuration for entry 3* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 3) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 3) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg0].pmp3cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp3cfg & 0x1) == 0) && ((csr_value.pmp3cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp3cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp3cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 3) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 3) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg0].pmp3cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp3cfg & 0x1) == 0) && ((csr_value.pmp3cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp3cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp3cfg; } } - # fall through: keep old value - return CSR[pmpcfg0].pmp3cfg; - pmp4cfg: - location: 39-32 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 4* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 38:37 ! _Reserved_ Writes shall be ignored. - h! A ! 36:35 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg0].pmp3cfg; + pmp4cfg: + location: 39-32 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 4* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 38:37 ! _Reserved_ Writes shall be ignored. + h! A ! 36:35 + a! Address matching mode. One of: - h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 4) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 4) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg0].pmp4cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp4cfg & 0x1) == 0) && ((csr_value.pmp4cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp4cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp4cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 4) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 4) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg0].pmp4cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp4cfg & 0x1) == 0) && ((csr_value.pmp4cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp4cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp4cfg; } } - # fall through: keep old value - return CSR[pmpcfg0].pmp4cfg; - pmp5cfg: - location: 47-40 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 5* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 46:45 ! _Reserved_ Writes shall be ignored. - h! A ! 44:43 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg0].pmp4cfg; + pmp5cfg: + location: 47-40 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 5* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 46:45 ! _Reserved_ Writes shall be ignored. + h! A ! 44:43 + a! Address matching mode. One of: - h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 5) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 5) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg0].pmp5cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp5cfg & 0x1) == 0) && ((csr_value.pmp5cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp5cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp5cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 5) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 5) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg0].pmp5cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp5cfg & 0x1) == 0) && ((csr_value.pmp5cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp5cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp5cfg; } } - # fall through: keep old value - return CSR[pmpcfg0].pmp5cfg; - pmp6cfg: - location: 55-48 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 6* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 54:53 ! _Reserved_ Writes shall be ignored. - h! A ! 52:51 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg0].pmp5cfg; + pmp6cfg: + location: 55-48 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 6* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 54:53 ! _Reserved_ Writes shall be ignored. + h! A ! 52:51 + a! Address matching mode. One of: - h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 6) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 6) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg0].pmp6cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp6cfg & 0x1) == 0) && ((csr_value.pmp6cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp6cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp6cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 6) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 6) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg0].pmp6cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp6cfg & 0x1) == 0) && ((csr_value.pmp6cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp6cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp6cfg; } } - # fall through: keep old value - return CSR[pmpcfg0].pmp6cfg; - pmp7cfg: - location: 63-56 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 7* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 62:61 ! _Reserved_ Writes shall be ignored. - h! A ! 60:59 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg0].pmp6cfg; + pmp7cfg: + location: 63-56 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 7* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 62:61 ! _Reserved_ Writes shall be ignored. + h! A ! 60:59 + a! Address matching mode. One of: - h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 7) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 7) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg0].pmp7cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp7cfg & 0x1) == 0) && ((csr_value.pmp7cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp7cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp7cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 7) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 7) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg0].pmp7cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp7cfg & 0x1) == 0) && ((csr_value.pmp7cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp7cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp7cfg; } } - # fall through: keep old value - return CSR[pmpcfg0].pmp7cfg; + } + # fall through: keep old value + return CSR[pmpcfg0].pmp7cfg; diff --git a/arch/csr/I/pmpcfg1.yaml b/arch/csr/I/pmpcfg1.yaml index 47061f3d3..b4dd1bb58 100644 --- a/arch/csr/I/pmpcfg1.yaml +++ b/arch/csr/I/pmpcfg1.yaml @@ -4,260 +4,262 @@ -pmpcfg1: - base: 32 # odd numbered pmpcfg registers do not exist in RV64 - long_name: PMP Configuration Register 1 - address: 0x3A1 - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp4cfg: - location: 7-0 - description: | - *PMP configuration for entry 4* +$schema: csr_schema.json# +kind: csr +name: pmpcfg1 +base: 32 # odd numbered pmpcfg registers do not exist in RV64 +long_name: PMP Configuration Register 1 +address: 0x3A1 +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp4cfg: + location: 7-0 + description: | + *PMP configuration for entry 4* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 4) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 4) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg1].pmp4cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp4cfg & 0x1) == 0) && ((csr_value.pmp4cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp4cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp4cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 4) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 4) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg1].pmp4cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp4cfg & 0x1) == 0) && ((csr_value.pmp4cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp4cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp4cfg; } } - # fall through: keep old value - return CSR[pmpcfg1].pmp4cfg; - pmp5cfg: - location: 15-8 - description: | - *PMP configuration for entry 5* + } + # fall through: keep old value + return CSR[pmpcfg1].pmp4cfg; + pmp5cfg: + location: 15-8 + description: | + *PMP configuration for entry 5* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 5) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 5) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg1].pmp5cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp5cfg & 0x1) == 0) && ((csr_value.pmp5cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp5cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp5cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 5) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 5) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg1].pmp5cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp5cfg & 0x1) == 0) && ((csr_value.pmp5cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp5cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp5cfg; } } - # fall through: keep old value - return CSR[pmpcfg1].pmp5cfg; - pmp6cfg: - location: 23-16 - description: | - *PMP configuration for entry 6* + } + # fall through: keep old value + return CSR[pmpcfg1].pmp5cfg; + pmp6cfg: + location: 23-16 + description: | + *PMP configuration for entry 6* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 6) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 6) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg1].pmp6cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp6cfg & 0x1) == 0) && ((csr_value.pmp6cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp6cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp6cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 6) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 6) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg1].pmp6cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp6cfg & 0x1) == 0) && ((csr_value.pmp6cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp6cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp6cfg; } } - # fall through: keep old value - return CSR[pmpcfg1].pmp6cfg; - pmp7cfg: - location: 31-24 - description: | - *PMP configuration for entry 7* + } + # fall through: keep old value + return CSR[pmpcfg1].pmp6cfg; + pmp7cfg: + location: 31-24 + description: | + *PMP configuration for entry 7* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 7) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 7) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg1].pmp7cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp7cfg & 0x1) == 0) && ((csr_value.pmp7cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp7cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp7cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 7) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 7) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg1].pmp7cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp7cfg & 0x1) == 0) && ((csr_value.pmp7cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp7cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp7cfg; } } - # fall through: keep old value - return CSR[pmpcfg1].pmp7cfg; + } + # fall through: keep old value + return CSR[pmpcfg1].pmp7cfg; diff --git a/arch/csr/I/pmpcfg10.yaml b/arch/csr/I/pmpcfg10.yaml index eca9a6029..b44572844 100644 --- a/arch/csr/I/pmpcfg10.yaml +++ b/arch/csr/I/pmpcfg10.yaml @@ -4,511 +4,513 @@ -pmpcfg10: - long_name: PMP Configuration Register 10 - address: 0x3AA - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp40cfg: - location: 7-0 - description: | - *PMP configuration for entry 40* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). +$schema: csr_schema.json# +kind: csr +name: pmpcfg10 +long_name: PMP Configuration Register 10 +address: 0x3AA +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp40cfg: + location: 7-0 + description: | + *PMP configuration for entry 40* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 40) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 40) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg10].pmp40cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp40cfg & 0x1) == 0) && ((csr_value.pmp40cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp40cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp40cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 40) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 40) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg10].pmp40cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp40cfg & 0x1) == 0) && ((csr_value.pmp40cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp40cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp40cfg; } } - # fall through: keep old value - return CSR[pmpcfg10].pmp40cfg; - pmp41cfg: - location: 15-8 - description: | - *PMP configuration for entry 41* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg10].pmp40cfg; + pmp41cfg: + location: 15-8 + description: | + *PMP configuration for entry 41* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 41) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 41) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg10].pmp41cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp41cfg & 0x1) == 0) && ((csr_value.pmp41cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp41cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp41cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 41) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 41) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg10].pmp41cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp41cfg & 0x1) == 0) && ((csr_value.pmp41cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp41cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp41cfg; } } - # fall through: keep old value - return CSR[pmpcfg10].pmp41cfg; - pmp42cfg: - location: 23-16 - description: | - *PMP configuration for entry 42* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg10].pmp41cfg; + pmp42cfg: + location: 23-16 + description: | + *PMP configuration for entry 42* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 42) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 42) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg10].pmp42cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp42cfg & 0x1) == 0) && ((csr_value.pmp42cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp42cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp42cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 42) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 42) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg10].pmp42cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp42cfg & 0x1) == 0) && ((csr_value.pmp42cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp42cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp42cfg; } } - # fall through: keep old value - return CSR[pmpcfg10].pmp42cfg; - pmp43cfg: - location: 31-24 - description: | - *PMP configuration for entry 43* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg10].pmp42cfg; + pmp43cfg: + location: 31-24 + description: | + *PMP configuration for entry 43* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 43) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 43) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg10].pmp43cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp43cfg & 0x1) == 0) && ((csr_value.pmp43cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp43cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp43cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 43) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 43) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg10].pmp43cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp43cfg & 0x1) == 0) && ((csr_value.pmp43cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp43cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp43cfg; } } - # fall through: keep old value - return CSR[pmpcfg10].pmp43cfg; - pmp44cfg: - location: 39-32 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 44* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 38:37 ! _Reserved_ Writes shall be ignored. - h! A ! 36:35 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg10].pmp43cfg; + pmp44cfg: + location: 39-32 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 44* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 38:37 ! _Reserved_ Writes shall be ignored. + h! A ! 36:35 + a! Address matching mode. One of: - h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 44) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 44) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg10].pmp44cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp44cfg & 0x1) == 0) && ((csr_value.pmp44cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp44cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp44cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 44) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 44) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg10].pmp44cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp44cfg & 0x1) == 0) && ((csr_value.pmp44cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp44cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp44cfg; } } - # fall through: keep old value - return CSR[pmpcfg10].pmp44cfg; - pmp45cfg: - location: 47-40 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 45* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 46:45 ! _Reserved_ Writes shall be ignored. - h! A ! 44:43 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg10].pmp44cfg; + pmp45cfg: + location: 47-40 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 45* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 46:45 ! _Reserved_ Writes shall be ignored. + h! A ! 44:43 + a! Address matching mode. One of: - h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 45) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 45) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg10].pmp45cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp45cfg & 0x1) == 0) && ((csr_value.pmp45cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp45cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp45cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 45) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 45) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg10].pmp45cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp45cfg & 0x1) == 0) && ((csr_value.pmp45cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp45cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp45cfg; } } - # fall through: keep old value - return CSR[pmpcfg10].pmp45cfg; - pmp46cfg: - location: 55-48 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 46* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 54:53 ! _Reserved_ Writes shall be ignored. - h! A ! 52:51 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg10].pmp45cfg; + pmp46cfg: + location: 55-48 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 46* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 54:53 ! _Reserved_ Writes shall be ignored. + h! A ! 52:51 + a! Address matching mode. One of: - h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 46) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 46) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg10].pmp46cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp46cfg & 0x1) == 0) && ((csr_value.pmp46cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp46cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp46cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 46) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 46) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg10].pmp46cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp46cfg & 0x1) == 0) && ((csr_value.pmp46cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp46cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp46cfg; } } - # fall through: keep old value - return CSR[pmpcfg10].pmp46cfg; - pmp47cfg: - location: 63-56 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 47* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 62:61 ! _Reserved_ Writes shall be ignored. - h! A ! 60:59 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg10].pmp46cfg; + pmp47cfg: + location: 63-56 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 47* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 62:61 ! _Reserved_ Writes shall be ignored. + h! A ! 60:59 + a! Address matching mode. One of: - h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 47) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 47) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg10].pmp47cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp47cfg & 0x1) == 0) && ((csr_value.pmp47cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp47cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp47cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 47) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 47) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg10].pmp47cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp47cfg & 0x1) == 0) && ((csr_value.pmp47cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp47cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp47cfg; } } - # fall through: keep old value - return CSR[pmpcfg10].pmp47cfg; + } + # fall through: keep old value + return CSR[pmpcfg10].pmp47cfg; diff --git a/arch/csr/I/pmpcfg11.yaml b/arch/csr/I/pmpcfg11.yaml index 63d38cc49..cd94a72b1 100644 --- a/arch/csr/I/pmpcfg11.yaml +++ b/arch/csr/I/pmpcfg11.yaml @@ -4,260 +4,262 @@ -pmpcfg11: - base: 32 # odd numbered pmpcfg registers do not exist in RV64 - long_name: PMP Configuration Register 11 - address: 0x3AB - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp44cfg: - location: 7-0 - description: | - *PMP configuration for entry 44* +$schema: csr_schema.json# +kind: csr +name: pmpcfg11 +base: 32 # odd numbered pmpcfg registers do not exist in RV64 +long_name: PMP Configuration Register 11 +address: 0x3AB +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp44cfg: + location: 7-0 + description: | + *PMP configuration for entry 44* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 44) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 44) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg11].pmp44cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp44cfg & 0x1) == 0) && ((csr_value.pmp44cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp44cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp44cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 44) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 44) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg11].pmp44cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp44cfg & 0x1) == 0) && ((csr_value.pmp44cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp44cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp44cfg; } } - # fall through: keep old value - return CSR[pmpcfg11].pmp44cfg; - pmp45cfg: - location: 15-8 - description: | - *PMP configuration for entry 45* + } + # fall through: keep old value + return CSR[pmpcfg11].pmp44cfg; + pmp45cfg: + location: 15-8 + description: | + *PMP configuration for entry 45* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 45) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 45) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg11].pmp45cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp45cfg & 0x1) == 0) && ((csr_value.pmp45cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp45cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp45cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 45) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 45) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg11].pmp45cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp45cfg & 0x1) == 0) && ((csr_value.pmp45cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp45cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp45cfg; } } - # fall through: keep old value - return CSR[pmpcfg11].pmp45cfg; - pmp46cfg: - location: 23-16 - description: | - *PMP configuration for entry 46* + } + # fall through: keep old value + return CSR[pmpcfg11].pmp45cfg; + pmp46cfg: + location: 23-16 + description: | + *PMP configuration for entry 46* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 46) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 46) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg11].pmp46cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp46cfg & 0x1) == 0) && ((csr_value.pmp46cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp46cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp46cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 46) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 46) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg11].pmp46cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp46cfg & 0x1) == 0) && ((csr_value.pmp46cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp46cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp46cfg; } } - # fall through: keep old value - return CSR[pmpcfg11].pmp46cfg; - pmp47cfg: - location: 31-24 - description: | - *PMP configuration for entry 47* + } + # fall through: keep old value + return CSR[pmpcfg11].pmp46cfg; + pmp47cfg: + location: 31-24 + description: | + *PMP configuration for entry 47* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 47) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 47) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg11].pmp47cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp47cfg & 0x1) == 0) && ((csr_value.pmp47cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp47cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp47cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 47) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 47) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg11].pmp47cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp47cfg & 0x1) == 0) && ((csr_value.pmp47cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp47cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp47cfg; } } - # fall through: keep old value - return CSR[pmpcfg11].pmp47cfg; + } + # fall through: keep old value + return CSR[pmpcfg11].pmp47cfg; diff --git a/arch/csr/I/pmpcfg12.yaml b/arch/csr/I/pmpcfg12.yaml index 15b3c2143..fa1e34583 100644 --- a/arch/csr/I/pmpcfg12.yaml +++ b/arch/csr/I/pmpcfg12.yaml @@ -4,511 +4,513 @@ -pmpcfg12: - long_name: PMP Configuration Register 12 - address: 0x3AC - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp48cfg: - location: 7-0 - description: | - *PMP configuration for entry 48* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). +$schema: csr_schema.json# +kind: csr +name: pmpcfg12 +long_name: PMP Configuration Register 12 +address: 0x3AC +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp48cfg: + location: 7-0 + description: | + *PMP configuration for entry 48* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 48) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 48) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg12].pmp48cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp48cfg & 0x1) == 0) && ((csr_value.pmp48cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp48cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp48cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 48) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 48) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg12].pmp48cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp48cfg & 0x1) == 0) && ((csr_value.pmp48cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp48cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp48cfg; } } - # fall through: keep old value - return CSR[pmpcfg12].pmp48cfg; - pmp49cfg: - location: 15-8 - description: | - *PMP configuration for entry 49* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg12].pmp48cfg; + pmp49cfg: + location: 15-8 + description: | + *PMP configuration for entry 49* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 49) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 49) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg12].pmp49cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp49cfg & 0x1) == 0) && ((csr_value.pmp49cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp49cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp49cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 49) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 49) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg12].pmp49cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp49cfg & 0x1) == 0) && ((csr_value.pmp49cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp49cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp49cfg; } } - # fall through: keep old value - return CSR[pmpcfg12].pmp49cfg; - pmp50cfg: - location: 23-16 - description: | - *PMP configuration for entry 50* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg12].pmp49cfg; + pmp50cfg: + location: 23-16 + description: | + *PMP configuration for entry 50* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 50) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 50) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg12].pmp50cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp50cfg & 0x1) == 0) && ((csr_value.pmp50cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp50cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp50cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 50) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 50) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg12].pmp50cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp50cfg & 0x1) == 0) && ((csr_value.pmp50cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp50cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp50cfg; } } - # fall through: keep old value - return CSR[pmpcfg12].pmp50cfg; - pmp51cfg: - location: 31-24 - description: | - *PMP configuration for entry 51* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg12].pmp50cfg; + pmp51cfg: + location: 31-24 + description: | + *PMP configuration for entry 51* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 51) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 51) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg12].pmp51cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp51cfg & 0x1) == 0) && ((csr_value.pmp51cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp51cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp51cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 51) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 51) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg12].pmp51cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp51cfg & 0x1) == 0) && ((csr_value.pmp51cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp51cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp51cfg; } } - # fall through: keep old value - return CSR[pmpcfg12].pmp51cfg; - pmp52cfg: - location: 39-32 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 52* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 38:37 ! _Reserved_ Writes shall be ignored. - h! A ! 36:35 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg12].pmp51cfg; + pmp52cfg: + location: 39-32 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 52* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 38:37 ! _Reserved_ Writes shall be ignored. + h! A ! 36:35 + a! Address matching mode. One of: - h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 52) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 52) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg12].pmp52cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp52cfg & 0x1) == 0) && ((csr_value.pmp52cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp52cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp52cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 52) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 52) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg12].pmp52cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp52cfg & 0x1) == 0) && ((csr_value.pmp52cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp52cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp52cfg; } } - # fall through: keep old value - return CSR[pmpcfg12].pmp52cfg; - pmp53cfg: - location: 47-40 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 53* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 46:45 ! _Reserved_ Writes shall be ignored. - h! A ! 44:43 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg12].pmp52cfg; + pmp53cfg: + location: 47-40 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 53* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 46:45 ! _Reserved_ Writes shall be ignored. + h! A ! 44:43 + a! Address matching mode. One of: - h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 53) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 53) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg12].pmp53cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp53cfg & 0x1) == 0) && ((csr_value.pmp53cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp53cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp53cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 53) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 53) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg12].pmp53cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp53cfg & 0x1) == 0) && ((csr_value.pmp53cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp53cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp53cfg; } } - # fall through: keep old value - return CSR[pmpcfg12].pmp53cfg; - pmp54cfg: - location: 55-48 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 54* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 54:53 ! _Reserved_ Writes shall be ignored. - h! A ! 52:51 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg12].pmp53cfg; + pmp54cfg: + location: 55-48 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 54* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 54:53 ! _Reserved_ Writes shall be ignored. + h! A ! 52:51 + a! Address matching mode. One of: - h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 54) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 54) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg12].pmp54cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp54cfg & 0x1) == 0) && ((csr_value.pmp54cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp54cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp54cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 54) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 54) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg12].pmp54cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp54cfg & 0x1) == 0) && ((csr_value.pmp54cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp54cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp54cfg; } } - # fall through: keep old value - return CSR[pmpcfg12].pmp54cfg; - pmp55cfg: - location: 63-56 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 55* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 62:61 ! _Reserved_ Writes shall be ignored. - h! A ! 60:59 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg12].pmp54cfg; + pmp55cfg: + location: 63-56 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 55* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 62:61 ! _Reserved_ Writes shall be ignored. + h! A ! 60:59 + a! Address matching mode. One of: - h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 55) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 55) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg12].pmp55cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp55cfg & 0x1) == 0) && ((csr_value.pmp55cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp55cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp55cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 55) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 55) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg12].pmp55cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp55cfg & 0x1) == 0) && ((csr_value.pmp55cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp55cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp55cfg; } } - # fall through: keep old value - return CSR[pmpcfg12].pmp55cfg; + } + # fall through: keep old value + return CSR[pmpcfg12].pmp55cfg; diff --git a/arch/csr/I/pmpcfg13.yaml b/arch/csr/I/pmpcfg13.yaml index 7b418cf86..207a5aa77 100644 --- a/arch/csr/I/pmpcfg13.yaml +++ b/arch/csr/I/pmpcfg13.yaml @@ -4,260 +4,262 @@ -pmpcfg13: - base: 32 # odd numbered pmpcfg registers do not exist in RV64 - long_name: PMP Configuration Register 13 - address: 0x3AD - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp52cfg: - location: 7-0 - description: | - *PMP configuration for entry 52* +$schema: csr_schema.json# +kind: csr +name: pmpcfg13 +base: 32 # odd numbered pmpcfg registers do not exist in RV64 +long_name: PMP Configuration Register 13 +address: 0x3AD +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp52cfg: + location: 7-0 + description: | + *PMP configuration for entry 52* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 52) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 52) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg13].pmp52cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp52cfg & 0x1) == 0) && ((csr_value.pmp52cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp52cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp52cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 52) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 52) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg13].pmp52cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp52cfg & 0x1) == 0) && ((csr_value.pmp52cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp52cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp52cfg; } } - # fall through: keep old value - return CSR[pmpcfg13].pmp52cfg; - pmp53cfg: - location: 15-8 - description: | - *PMP configuration for entry 53* + } + # fall through: keep old value + return CSR[pmpcfg13].pmp52cfg; + pmp53cfg: + location: 15-8 + description: | + *PMP configuration for entry 53* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 53) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 53) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg13].pmp53cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp53cfg & 0x1) == 0) && ((csr_value.pmp53cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp53cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp53cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 53) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 53) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg13].pmp53cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp53cfg & 0x1) == 0) && ((csr_value.pmp53cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp53cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp53cfg; } } - # fall through: keep old value - return CSR[pmpcfg13].pmp53cfg; - pmp54cfg: - location: 23-16 - description: | - *PMP configuration for entry 54* + } + # fall through: keep old value + return CSR[pmpcfg13].pmp53cfg; + pmp54cfg: + location: 23-16 + description: | + *PMP configuration for entry 54* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 54) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 54) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg13].pmp54cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp54cfg & 0x1) == 0) && ((csr_value.pmp54cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp54cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp54cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 54) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 54) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg13].pmp54cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp54cfg & 0x1) == 0) && ((csr_value.pmp54cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp54cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp54cfg; } } - # fall through: keep old value - return CSR[pmpcfg13].pmp54cfg; - pmp55cfg: - location: 31-24 - description: | - *PMP configuration for entry 55* + } + # fall through: keep old value + return CSR[pmpcfg13].pmp54cfg; + pmp55cfg: + location: 31-24 + description: | + *PMP configuration for entry 55* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 55) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 55) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg13].pmp55cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp55cfg & 0x1) == 0) && ((csr_value.pmp55cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp55cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp55cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 55) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 55) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg13].pmp55cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp55cfg & 0x1) == 0) && ((csr_value.pmp55cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp55cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp55cfg; } } - # fall through: keep old value - return CSR[pmpcfg13].pmp55cfg; + } + # fall through: keep old value + return CSR[pmpcfg13].pmp55cfg; diff --git a/arch/csr/I/pmpcfg14.yaml b/arch/csr/I/pmpcfg14.yaml index 699900afe..f17cc62b1 100644 --- a/arch/csr/I/pmpcfg14.yaml +++ b/arch/csr/I/pmpcfg14.yaml @@ -4,511 +4,513 @@ -pmpcfg14: - long_name: PMP Configuration Register 14 - address: 0x3AE - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp56cfg: - location: 7-0 - description: | - *PMP configuration for entry 56* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). +$schema: csr_schema.json# +kind: csr +name: pmpcfg14 +long_name: PMP Configuration Register 14 +address: 0x3AE +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp56cfg: + location: 7-0 + description: | + *PMP configuration for entry 56* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 56) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 56) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg14].pmp56cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp56cfg & 0x1) == 0) && ((csr_value.pmp56cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp56cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp56cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 56) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 56) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg14].pmp56cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp56cfg & 0x1) == 0) && ((csr_value.pmp56cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp56cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp56cfg; } } - # fall through: keep old value - return CSR[pmpcfg14].pmp56cfg; - pmp57cfg: - location: 15-8 - description: | - *PMP configuration for entry 57* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg14].pmp56cfg; + pmp57cfg: + location: 15-8 + description: | + *PMP configuration for entry 57* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 57) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 57) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg14].pmp57cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp57cfg & 0x1) == 0) && ((csr_value.pmp57cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp57cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp57cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 57) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 57) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg14].pmp57cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp57cfg & 0x1) == 0) && ((csr_value.pmp57cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp57cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp57cfg; } } - # fall through: keep old value - return CSR[pmpcfg14].pmp57cfg; - pmp58cfg: - location: 23-16 - description: | - *PMP configuration for entry 58* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg14].pmp57cfg; + pmp58cfg: + location: 23-16 + description: | + *PMP configuration for entry 58* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 58) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 58) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg14].pmp58cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp58cfg & 0x1) == 0) && ((csr_value.pmp58cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp58cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp58cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 58) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 58) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg14].pmp58cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp58cfg & 0x1) == 0) && ((csr_value.pmp58cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp58cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp58cfg; } } - # fall through: keep old value - return CSR[pmpcfg14].pmp58cfg; - pmp59cfg: - location: 31-24 - description: | - *PMP configuration for entry 59* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg14].pmp58cfg; + pmp59cfg: + location: 31-24 + description: | + *PMP configuration for entry 59* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 59) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 59) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg14].pmp59cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp59cfg & 0x1) == 0) && ((csr_value.pmp59cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp59cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp59cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 59) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 59) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg14].pmp59cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp59cfg & 0x1) == 0) && ((csr_value.pmp59cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp59cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp59cfg; } } - # fall through: keep old value - return CSR[pmpcfg14].pmp59cfg; - pmp60cfg: - location: 39-32 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 60* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 38:37 ! _Reserved_ Writes shall be ignored. - h! A ! 36:35 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg14].pmp59cfg; + pmp60cfg: + location: 39-32 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 60* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 38:37 ! _Reserved_ Writes shall be ignored. + h! A ! 36:35 + a! Address matching mode. One of: - h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 60) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 60) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg14].pmp60cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp60cfg & 0x1) == 0) && ((csr_value.pmp60cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp60cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp60cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 60) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 60) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg14].pmp60cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp60cfg & 0x1) == 0) && ((csr_value.pmp60cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp60cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp60cfg; } } - # fall through: keep old value - return CSR[pmpcfg14].pmp60cfg; - pmp61cfg: - location: 47-40 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 61* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 46:45 ! _Reserved_ Writes shall be ignored. - h! A ! 44:43 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg14].pmp60cfg; + pmp61cfg: + location: 47-40 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 61* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 46:45 ! _Reserved_ Writes shall be ignored. + h! A ! 44:43 + a! Address matching mode. One of: - h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 61) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 61) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg14].pmp61cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp61cfg & 0x1) == 0) && ((csr_value.pmp61cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp61cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp61cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 61) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 61) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg14].pmp61cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp61cfg & 0x1) == 0) && ((csr_value.pmp61cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp61cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp61cfg; } } - # fall through: keep old value - return CSR[pmpcfg14].pmp61cfg; - pmp62cfg: - location: 55-48 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 62* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 54:53 ! _Reserved_ Writes shall be ignored. - h! A ! 52:51 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg14].pmp61cfg; + pmp62cfg: + location: 55-48 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 62* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 54:53 ! _Reserved_ Writes shall be ignored. + h! A ! 52:51 + a! Address matching mode. One of: - h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 62) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 62) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg14].pmp62cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp62cfg & 0x1) == 0) && ((csr_value.pmp62cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp62cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp62cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 62) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 62) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg14].pmp62cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp62cfg & 0x1) == 0) && ((csr_value.pmp62cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp62cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp62cfg; } } - # fall through: keep old value - return CSR[pmpcfg14].pmp62cfg; - pmp63cfg: - location: 63-56 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 63* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 62:61 ! _Reserved_ Writes shall be ignored. - h! A ! 60:59 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg14].pmp62cfg; + pmp63cfg: + location: 63-56 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 63* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 62:61 ! _Reserved_ Writes shall be ignored. + h! A ! 60:59 + a! Address matching mode. One of: - h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 63) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 63) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg14].pmp63cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp63cfg & 0x1) == 0) && ((csr_value.pmp63cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp63cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp63cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 63) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 63) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg14].pmp63cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp63cfg & 0x1) == 0) && ((csr_value.pmp63cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp63cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp63cfg; } } - # fall through: keep old value - return CSR[pmpcfg14].pmp63cfg; + } + # fall through: keep old value + return CSR[pmpcfg14].pmp63cfg; diff --git a/arch/csr/I/pmpcfg15.yaml b/arch/csr/I/pmpcfg15.yaml index 58f9a8d16..8b267586b 100644 --- a/arch/csr/I/pmpcfg15.yaml +++ b/arch/csr/I/pmpcfg15.yaml @@ -4,260 +4,262 @@ -pmpcfg15: - base: 32 # odd numbered pmpcfg registers do not exist in RV64 - long_name: PMP Configuration Register 15 - address: 0x3AF - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp60cfg: - location: 7-0 - description: | - *PMP configuration for entry 60* +$schema: csr_schema.json# +kind: csr +name: pmpcfg15 +base: 32 # odd numbered pmpcfg registers do not exist in RV64 +long_name: PMP Configuration Register 15 +address: 0x3AF +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp60cfg: + location: 7-0 + description: | + *PMP configuration for entry 60* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 60) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 60) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg15].pmp60cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp60cfg & 0x1) == 0) && ((csr_value.pmp60cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp60cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp60cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 60) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 60) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg15].pmp60cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp60cfg & 0x1) == 0) && ((csr_value.pmp60cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp60cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp60cfg; } } - # fall through: keep old value - return CSR[pmpcfg15].pmp60cfg; - pmp61cfg: - location: 15-8 - description: | - *PMP configuration for entry 61* + } + # fall through: keep old value + return CSR[pmpcfg15].pmp60cfg; + pmp61cfg: + location: 15-8 + description: | + *PMP configuration for entry 61* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 61) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 61) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg15].pmp61cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp61cfg & 0x1) == 0) && ((csr_value.pmp61cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp61cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp61cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 61) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 61) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg15].pmp61cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp61cfg & 0x1) == 0) && ((csr_value.pmp61cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp61cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp61cfg; } } - # fall through: keep old value - return CSR[pmpcfg15].pmp61cfg; - pmp62cfg: - location: 23-16 - description: | - *PMP configuration for entry 62* + } + # fall through: keep old value + return CSR[pmpcfg15].pmp61cfg; + pmp62cfg: + location: 23-16 + description: | + *PMP configuration for entry 62* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 62) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 62) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg15].pmp62cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp62cfg & 0x1) == 0) && ((csr_value.pmp62cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp62cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp62cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 62) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 62) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg15].pmp62cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp62cfg & 0x1) == 0) && ((csr_value.pmp62cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp62cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp62cfg; } } - # fall through: keep old value - return CSR[pmpcfg15].pmp62cfg; - pmp63cfg: - location: 31-24 - description: | - *PMP configuration for entry 63* + } + # fall through: keep old value + return CSR[pmpcfg15].pmp62cfg; + pmp63cfg: + location: 31-24 + description: | + *PMP configuration for entry 63* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 63) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 63) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg15].pmp63cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp63cfg & 0x1) == 0) && ((csr_value.pmp63cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp63cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp63cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 63) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 63) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg15].pmp63cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp63cfg & 0x1) == 0) && ((csr_value.pmp63cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp63cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp63cfg; } } - # fall through: keep old value - return CSR[pmpcfg15].pmp63cfg; + } + # fall through: keep old value + return CSR[pmpcfg15].pmp63cfg; diff --git a/arch/csr/I/pmpcfg2.yaml b/arch/csr/I/pmpcfg2.yaml index 4efc7473f..5a502d96b 100644 --- a/arch/csr/I/pmpcfg2.yaml +++ b/arch/csr/I/pmpcfg2.yaml @@ -4,511 +4,513 @@ -pmpcfg2: - long_name: PMP Configuration Register 2 - address: 0x3A2 - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp8cfg: - location: 7-0 - description: | - *PMP configuration for entry 8* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). +$schema: csr_schema.json# +kind: csr +name: pmpcfg2 +long_name: PMP Configuration Register 2 +address: 0x3A2 +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp8cfg: + location: 7-0 + description: | + *PMP configuration for entry 8* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 8) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 8) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg2].pmp8cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp8cfg & 0x1) == 0) && ((csr_value.pmp8cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp8cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp8cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 8) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 8) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg2].pmp8cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp8cfg & 0x1) == 0) && ((csr_value.pmp8cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp8cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp8cfg; } } - # fall through: keep old value - return CSR[pmpcfg2].pmp8cfg; - pmp9cfg: - location: 15-8 - description: | - *PMP configuration for entry 9* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg2].pmp8cfg; + pmp9cfg: + location: 15-8 + description: | + *PMP configuration for entry 9* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 9) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 9) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg2].pmp9cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp9cfg & 0x1) == 0) && ((csr_value.pmp9cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp9cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp9cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 9) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 9) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg2].pmp9cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp9cfg & 0x1) == 0) && ((csr_value.pmp9cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp9cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp9cfg; } } - # fall through: keep old value - return CSR[pmpcfg2].pmp9cfg; - pmp10cfg: - location: 23-16 - description: | - *PMP configuration for entry 10* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg2].pmp9cfg; + pmp10cfg: + location: 23-16 + description: | + *PMP configuration for entry 10* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 10) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 10) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg2].pmp10cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp10cfg & 0x1) == 0) && ((csr_value.pmp10cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp10cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp10cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 10) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 10) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg2].pmp10cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp10cfg & 0x1) == 0) && ((csr_value.pmp10cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp10cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp10cfg; } } - # fall through: keep old value - return CSR[pmpcfg2].pmp10cfg; - pmp11cfg: - location: 31-24 - description: | - *PMP configuration for entry 11* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg2].pmp10cfg; + pmp11cfg: + location: 31-24 + description: | + *PMP configuration for entry 11* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 11) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 11) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg2].pmp11cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp11cfg & 0x1) == 0) && ((csr_value.pmp11cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp11cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp11cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 11) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 11) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg2].pmp11cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp11cfg & 0x1) == 0) && ((csr_value.pmp11cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp11cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp11cfg; } } - # fall through: keep old value - return CSR[pmpcfg2].pmp11cfg; - pmp12cfg: - location: 39-32 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 12* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 38:37 ! _Reserved_ Writes shall be ignored. - h! A ! 36:35 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg2].pmp11cfg; + pmp12cfg: + location: 39-32 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 12* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 38:37 ! _Reserved_ Writes shall be ignored. + h! A ! 36:35 + a! Address matching mode. One of: - h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 12) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 12) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg2].pmp12cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp12cfg & 0x1) == 0) && ((csr_value.pmp12cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp12cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp12cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 12) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 12) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg2].pmp12cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp12cfg & 0x1) == 0) && ((csr_value.pmp12cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp12cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp12cfg; } } - # fall through: keep old value - return CSR[pmpcfg2].pmp12cfg; - pmp13cfg: - location: 47-40 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 13* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 46:45 ! _Reserved_ Writes shall be ignored. - h! A ! 44:43 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg2].pmp12cfg; + pmp13cfg: + location: 47-40 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 13* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 46:45 ! _Reserved_ Writes shall be ignored. + h! A ! 44:43 + a! Address matching mode. One of: - h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 13) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 13) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg2].pmp13cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp13cfg & 0x1) == 0) && ((csr_value.pmp13cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp13cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp13cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 13) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 13) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg2].pmp13cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp13cfg & 0x1) == 0) && ((csr_value.pmp13cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp13cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp13cfg; } } - # fall through: keep old value - return CSR[pmpcfg2].pmp13cfg; - pmp14cfg: - location: 55-48 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 14* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 54:53 ! _Reserved_ Writes shall be ignored. - h! A ! 52:51 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg2].pmp13cfg; + pmp14cfg: + location: 55-48 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 14* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 54:53 ! _Reserved_ Writes shall be ignored. + h! A ! 52:51 + a! Address matching mode. One of: - h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 14) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 14) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg2].pmp14cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp14cfg & 0x1) == 0) && ((csr_value.pmp14cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp14cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp14cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 14) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 14) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg2].pmp14cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp14cfg & 0x1) == 0) && ((csr_value.pmp14cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp14cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp14cfg; } } - # fall through: keep old value - return CSR[pmpcfg2].pmp14cfg; - pmp15cfg: - location: 63-56 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 15* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 62:61 ! _Reserved_ Writes shall be ignored. - h! A ! 60:59 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg2].pmp14cfg; + pmp15cfg: + location: 63-56 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 15* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 62:61 ! _Reserved_ Writes shall be ignored. + h! A ! 60:59 + a! Address matching mode. One of: - h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 15) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 15) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg2].pmp15cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp15cfg & 0x1) == 0) && ((csr_value.pmp15cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp15cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp15cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 15) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 15) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg2].pmp15cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp15cfg & 0x1) == 0) && ((csr_value.pmp15cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp15cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp15cfg; } } - # fall through: keep old value - return CSR[pmpcfg2].pmp15cfg; + } + # fall through: keep old value + return CSR[pmpcfg2].pmp15cfg; diff --git a/arch/csr/I/pmpcfg3.yaml b/arch/csr/I/pmpcfg3.yaml index c118f5d90..d1a704789 100644 --- a/arch/csr/I/pmpcfg3.yaml +++ b/arch/csr/I/pmpcfg3.yaml @@ -4,260 +4,262 @@ -pmpcfg3: - base: 32 # odd numbered pmpcfg registers do not exist in RV64 - long_name: PMP Configuration Register 3 - address: 0x3A3 - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp12cfg: - location: 7-0 - description: | - *PMP configuration for entry 12* +$schema: csr_schema.json# +kind: csr +name: pmpcfg3 +base: 32 # odd numbered pmpcfg registers do not exist in RV64 +long_name: PMP Configuration Register 3 +address: 0x3A3 +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp12cfg: + location: 7-0 + description: | + *PMP configuration for entry 12* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 12) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 12) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg3].pmp12cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp12cfg & 0x1) == 0) && ((csr_value.pmp12cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp12cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp12cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 12) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 12) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg3].pmp12cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp12cfg & 0x1) == 0) && ((csr_value.pmp12cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp12cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp12cfg; } } - # fall through: keep old value - return CSR[pmpcfg3].pmp12cfg; - pmp13cfg: - location: 15-8 - description: | - *PMP configuration for entry 13* + } + # fall through: keep old value + return CSR[pmpcfg3].pmp12cfg; + pmp13cfg: + location: 15-8 + description: | + *PMP configuration for entry 13* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 13) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 13) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg3].pmp13cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp13cfg & 0x1) == 0) && ((csr_value.pmp13cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp13cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp13cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 13) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 13) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg3].pmp13cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp13cfg & 0x1) == 0) && ((csr_value.pmp13cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp13cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp13cfg; } } - # fall through: keep old value - return CSR[pmpcfg3].pmp13cfg; - pmp14cfg: - location: 23-16 - description: | - *PMP configuration for entry 14* + } + # fall through: keep old value + return CSR[pmpcfg3].pmp13cfg; + pmp14cfg: + location: 23-16 + description: | + *PMP configuration for entry 14* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 14) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 14) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg3].pmp14cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp14cfg & 0x1) == 0) && ((csr_value.pmp14cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp14cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp14cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 14) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 14) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg3].pmp14cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp14cfg & 0x1) == 0) && ((csr_value.pmp14cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp14cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp14cfg; } } - # fall through: keep old value - return CSR[pmpcfg3].pmp14cfg; - pmp15cfg: - location: 31-24 - description: | - *PMP configuration for entry 15* + } + # fall through: keep old value + return CSR[pmpcfg3].pmp14cfg; + pmp15cfg: + location: 31-24 + description: | + *PMP configuration for entry 15* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 15) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 15) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg3].pmp15cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp15cfg & 0x1) == 0) && ((csr_value.pmp15cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp15cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp15cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 15) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 15) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg3].pmp15cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp15cfg & 0x1) == 0) && ((csr_value.pmp15cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp15cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp15cfg; } } - # fall through: keep old value - return CSR[pmpcfg3].pmp15cfg; + } + # fall through: keep old value + return CSR[pmpcfg3].pmp15cfg; diff --git a/arch/csr/I/pmpcfg4.yaml b/arch/csr/I/pmpcfg4.yaml index e1739752a..ae6a9c6b5 100644 --- a/arch/csr/I/pmpcfg4.yaml +++ b/arch/csr/I/pmpcfg4.yaml @@ -4,511 +4,513 @@ -pmpcfg4: - long_name: PMP Configuration Register 4 - address: 0x3A4 - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp16cfg: - location: 7-0 - description: | - *PMP configuration for entry 16* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). +$schema: csr_schema.json# +kind: csr +name: pmpcfg4 +long_name: PMP Configuration Register 4 +address: 0x3A4 +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp16cfg: + location: 7-0 + description: | + *PMP configuration for entry 16* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 16) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 16) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg4].pmp16cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp16cfg & 0x1) == 0) && ((csr_value.pmp16cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp16cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp16cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 16) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 16) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg4].pmp16cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp16cfg & 0x1) == 0) && ((csr_value.pmp16cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp16cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp16cfg; } } - # fall through: keep old value - return CSR[pmpcfg4].pmp16cfg; - pmp17cfg: - location: 15-8 - description: | - *PMP configuration for entry 17* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg4].pmp16cfg; + pmp17cfg: + location: 15-8 + description: | + *PMP configuration for entry 17* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 17) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 17) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg4].pmp17cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp17cfg & 0x1) == 0) && ((csr_value.pmp17cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp17cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp17cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 17) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 17) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg4].pmp17cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp17cfg & 0x1) == 0) && ((csr_value.pmp17cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp17cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp17cfg; } } - # fall through: keep old value - return CSR[pmpcfg4].pmp17cfg; - pmp18cfg: - location: 23-16 - description: | - *PMP configuration for entry 18* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg4].pmp17cfg; + pmp18cfg: + location: 23-16 + description: | + *PMP configuration for entry 18* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 18) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 18) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg4].pmp18cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp18cfg & 0x1) == 0) && ((csr_value.pmp18cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp18cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp18cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 18) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 18) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg4].pmp18cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp18cfg & 0x1) == 0) && ((csr_value.pmp18cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp18cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp18cfg; } } - # fall through: keep old value - return CSR[pmpcfg4].pmp18cfg; - pmp19cfg: - location: 31-24 - description: | - *PMP configuration for entry 19* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg4].pmp18cfg; + pmp19cfg: + location: 31-24 + description: | + *PMP configuration for entry 19* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 19) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 19) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg4].pmp19cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp19cfg & 0x1) == 0) && ((csr_value.pmp19cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp19cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp19cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 19) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 19) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg4].pmp19cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp19cfg & 0x1) == 0) && ((csr_value.pmp19cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp19cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp19cfg; } } - # fall through: keep old value - return CSR[pmpcfg4].pmp19cfg; - pmp20cfg: - location: 39-32 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 20* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 38:37 ! _Reserved_ Writes shall be ignored. - h! A ! 36:35 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg4].pmp19cfg; + pmp20cfg: + location: 39-32 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 20* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 38:37 ! _Reserved_ Writes shall be ignored. + h! A ! 36:35 + a! Address matching mode. One of: - h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 20) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 20) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg4].pmp20cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp20cfg & 0x1) == 0) && ((csr_value.pmp20cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp20cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp20cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 20) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 20) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg4].pmp20cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp20cfg & 0x1) == 0) && ((csr_value.pmp20cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp20cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp20cfg; } } - # fall through: keep old value - return CSR[pmpcfg4].pmp20cfg; - pmp21cfg: - location: 47-40 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 21* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 46:45 ! _Reserved_ Writes shall be ignored. - h! A ! 44:43 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg4].pmp20cfg; + pmp21cfg: + location: 47-40 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 21* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 46:45 ! _Reserved_ Writes shall be ignored. + h! A ! 44:43 + a! Address matching mode. One of: - h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 21) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 21) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg4].pmp21cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp21cfg & 0x1) == 0) && ((csr_value.pmp21cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp21cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp21cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 21) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 21) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg4].pmp21cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp21cfg & 0x1) == 0) && ((csr_value.pmp21cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp21cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp21cfg; } } - # fall through: keep old value - return CSR[pmpcfg4].pmp21cfg; - pmp22cfg: - location: 55-48 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 22* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 54:53 ! _Reserved_ Writes shall be ignored. - h! A ! 52:51 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg4].pmp21cfg; + pmp22cfg: + location: 55-48 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 22* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 54:53 ! _Reserved_ Writes shall be ignored. + h! A ! 52:51 + a! Address matching mode. One of: - h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 22) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 22) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg4].pmp22cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp22cfg & 0x1) == 0) && ((csr_value.pmp22cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp22cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp22cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 22) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 22) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg4].pmp22cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp22cfg & 0x1) == 0) && ((csr_value.pmp22cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp22cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp22cfg; } } - # fall through: keep old value - return CSR[pmpcfg4].pmp22cfg; - pmp23cfg: - location: 63-56 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 23* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 62:61 ! _Reserved_ Writes shall be ignored. - h! A ! 60:59 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg4].pmp22cfg; + pmp23cfg: + location: 63-56 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 23* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 62:61 ! _Reserved_ Writes shall be ignored. + h! A ! 60:59 + a! Address matching mode. One of: - h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 23) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 23) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg4].pmp23cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp23cfg & 0x1) == 0) && ((csr_value.pmp23cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp23cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp23cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 23) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 23) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg4].pmp23cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp23cfg & 0x1) == 0) && ((csr_value.pmp23cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp23cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp23cfg; } } - # fall through: keep old value - return CSR[pmpcfg4].pmp23cfg; + } + # fall through: keep old value + return CSR[pmpcfg4].pmp23cfg; diff --git a/arch/csr/I/pmpcfg5.yaml b/arch/csr/I/pmpcfg5.yaml index 9a4ff20f1..95585e539 100644 --- a/arch/csr/I/pmpcfg5.yaml +++ b/arch/csr/I/pmpcfg5.yaml @@ -4,260 +4,262 @@ -pmpcfg5: - base: 32 # odd numbered pmpcfg registers do not exist in RV64 - long_name: PMP Configuration Register 5 - address: 0x3A5 - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp20cfg: - location: 7-0 - description: | - *PMP configuration for entry 20* +$schema: csr_schema.json# +kind: csr +name: pmpcfg5 +base: 32 # odd numbered pmpcfg registers do not exist in RV64 +long_name: PMP Configuration Register 5 +address: 0x3A5 +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp20cfg: + location: 7-0 + description: | + *PMP configuration for entry 20* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 20) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 20) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg5].pmp20cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp20cfg & 0x1) == 0) && ((csr_value.pmp20cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp20cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp20cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 20) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 20) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg5].pmp20cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp20cfg & 0x1) == 0) && ((csr_value.pmp20cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp20cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp20cfg; } } - # fall through: keep old value - return CSR[pmpcfg5].pmp20cfg; - pmp21cfg: - location: 15-8 - description: | - *PMP configuration for entry 21* + } + # fall through: keep old value + return CSR[pmpcfg5].pmp20cfg; + pmp21cfg: + location: 15-8 + description: | + *PMP configuration for entry 21* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 21) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 21) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg5].pmp21cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp21cfg & 0x1) == 0) && ((csr_value.pmp21cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp21cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp21cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 21) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 21) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg5].pmp21cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp21cfg & 0x1) == 0) && ((csr_value.pmp21cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp21cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp21cfg; } } - # fall through: keep old value - return CSR[pmpcfg5].pmp21cfg; - pmp22cfg: - location: 23-16 - description: | - *PMP configuration for entry 22* + } + # fall through: keep old value + return CSR[pmpcfg5].pmp21cfg; + pmp22cfg: + location: 23-16 + description: | + *PMP configuration for entry 22* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 22) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 22) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg5].pmp22cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp22cfg & 0x1) == 0) && ((csr_value.pmp22cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp22cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp22cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 22) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 22) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg5].pmp22cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp22cfg & 0x1) == 0) && ((csr_value.pmp22cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp22cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp22cfg; } } - # fall through: keep old value - return CSR[pmpcfg5].pmp22cfg; - pmp23cfg: - location: 31-24 - description: | - *PMP configuration for entry 23* + } + # fall through: keep old value + return CSR[pmpcfg5].pmp22cfg; + pmp23cfg: + location: 31-24 + description: | + *PMP configuration for entry 23* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 23) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 23) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg5].pmp23cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp23cfg & 0x1) == 0) && ((csr_value.pmp23cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp23cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp23cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 23) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 23) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg5].pmp23cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp23cfg & 0x1) == 0) && ((csr_value.pmp23cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp23cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp23cfg; } } - # fall through: keep old value - return CSR[pmpcfg5].pmp23cfg; + } + # fall through: keep old value + return CSR[pmpcfg5].pmp23cfg; diff --git a/arch/csr/I/pmpcfg6.yaml b/arch/csr/I/pmpcfg6.yaml index c4f98dcf4..6fe859fb6 100644 --- a/arch/csr/I/pmpcfg6.yaml +++ b/arch/csr/I/pmpcfg6.yaml @@ -4,511 +4,513 @@ -pmpcfg6: - long_name: PMP Configuration Register 6 - address: 0x3A6 - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp24cfg: - location: 7-0 - description: | - *PMP configuration for entry 24* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). +$schema: csr_schema.json# +kind: csr +name: pmpcfg6 +long_name: PMP Configuration Register 6 +address: 0x3A6 +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp24cfg: + location: 7-0 + description: | + *PMP configuration for entry 24* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 24) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 24) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg6].pmp24cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp24cfg & 0x1) == 0) && ((csr_value.pmp24cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp24cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp24cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 24) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 24) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg6].pmp24cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp24cfg & 0x1) == 0) && ((csr_value.pmp24cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp24cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp24cfg; } } - # fall through: keep old value - return CSR[pmpcfg6].pmp24cfg; - pmp25cfg: - location: 15-8 - description: | - *PMP configuration for entry 25* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg6].pmp24cfg; + pmp25cfg: + location: 15-8 + description: | + *PMP configuration for entry 25* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 25) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 25) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg6].pmp25cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp25cfg & 0x1) == 0) && ((csr_value.pmp25cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp25cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp25cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 25) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 25) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg6].pmp25cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp25cfg & 0x1) == 0) && ((csr_value.pmp25cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp25cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp25cfg; } } - # fall through: keep old value - return CSR[pmpcfg6].pmp25cfg; - pmp26cfg: - location: 23-16 - description: | - *PMP configuration for entry 26* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg6].pmp25cfg; + pmp26cfg: + location: 23-16 + description: | + *PMP configuration for entry 26* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 26) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 26) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg6].pmp26cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp26cfg & 0x1) == 0) && ((csr_value.pmp26cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp26cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp26cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 26) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 26) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg6].pmp26cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp26cfg & 0x1) == 0) && ((csr_value.pmp26cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp26cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp26cfg; } } - # fall through: keep old value - return CSR[pmpcfg6].pmp26cfg; - pmp27cfg: - location: 31-24 - description: | - *PMP configuration for entry 27* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg6].pmp26cfg; + pmp27cfg: + location: 31-24 + description: | + *PMP configuration for entry 27* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 27) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 27) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg6].pmp27cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp27cfg & 0x1) == 0) && ((csr_value.pmp27cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp27cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp27cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 27) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 27) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg6].pmp27cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp27cfg & 0x1) == 0) && ((csr_value.pmp27cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp27cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp27cfg; } } - # fall through: keep old value - return CSR[pmpcfg6].pmp27cfg; - pmp28cfg: - location: 39-32 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 28* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 38:37 ! _Reserved_ Writes shall be ignored. - h! A ! 36:35 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg6].pmp27cfg; + pmp28cfg: + location: 39-32 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 28* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 38:37 ! _Reserved_ Writes shall be ignored. + h! A ! 36:35 + a! Address matching mode. One of: - h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 28) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 28) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg6].pmp28cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp28cfg & 0x1) == 0) && ((csr_value.pmp28cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp28cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp28cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 28) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 28) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg6].pmp28cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp28cfg & 0x1) == 0) && ((csr_value.pmp28cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp28cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp28cfg; } } - # fall through: keep old value - return CSR[pmpcfg6].pmp28cfg; - pmp29cfg: - location: 47-40 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 29* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 46:45 ! _Reserved_ Writes shall be ignored. - h! A ! 44:43 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg6].pmp28cfg; + pmp29cfg: + location: 47-40 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 29* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 46:45 ! _Reserved_ Writes shall be ignored. + h! A ! 44:43 + a! Address matching mode. One of: - h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 29) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 29) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg6].pmp29cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp29cfg & 0x1) == 0) && ((csr_value.pmp29cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp29cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp29cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 29) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 29) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg6].pmp29cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp29cfg & 0x1) == 0) && ((csr_value.pmp29cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp29cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp29cfg; } } - # fall through: keep old value - return CSR[pmpcfg6].pmp29cfg; - pmp30cfg: - location: 55-48 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 30* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 54:53 ! _Reserved_ Writes shall be ignored. - h! A ! 52:51 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg6].pmp29cfg; + pmp30cfg: + location: 55-48 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 30* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 54:53 ! _Reserved_ Writes shall be ignored. + h! A ! 52:51 + a! Address matching mode. One of: - h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 30) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 30) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg6].pmp30cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp30cfg & 0x1) == 0) && ((csr_value.pmp30cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp30cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp30cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 30) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 30) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg6].pmp30cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp30cfg & 0x1) == 0) && ((csr_value.pmp30cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp30cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp30cfg; } } - # fall through: keep old value - return CSR[pmpcfg6].pmp30cfg; - pmp31cfg: - location: 63-56 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 31* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 62:61 ! _Reserved_ Writes shall be ignored. - h! A ! 60:59 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg6].pmp30cfg; + pmp31cfg: + location: 63-56 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 31* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 62:61 ! _Reserved_ Writes shall be ignored. + h! A ! 60:59 + a! Address matching mode. One of: - h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 31) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 31) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg6].pmp31cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp31cfg & 0x1) == 0) && ((csr_value.pmp31cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp31cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp31cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 31) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 31) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg6].pmp31cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp31cfg & 0x1) == 0) && ((csr_value.pmp31cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp31cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp31cfg; } } - # fall through: keep old value - return CSR[pmpcfg6].pmp31cfg; + } + # fall through: keep old value + return CSR[pmpcfg6].pmp31cfg; diff --git a/arch/csr/I/pmpcfg7.yaml b/arch/csr/I/pmpcfg7.yaml index 6bc3cc76e..2639b5870 100644 --- a/arch/csr/I/pmpcfg7.yaml +++ b/arch/csr/I/pmpcfg7.yaml @@ -4,260 +4,262 @@ -pmpcfg7: - base: 32 # odd numbered pmpcfg registers do not exist in RV64 - long_name: PMP Configuration Register 7 - address: 0x3A7 - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp28cfg: - location: 7-0 - description: | - *PMP configuration for entry 28* +$schema: csr_schema.json# +kind: csr +name: pmpcfg7 +base: 32 # odd numbered pmpcfg registers do not exist in RV64 +long_name: PMP Configuration Register 7 +address: 0x3A7 +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp28cfg: + location: 7-0 + description: | + *PMP configuration for entry 28* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 28) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 28) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg7].pmp28cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp28cfg & 0x1) == 0) && ((csr_value.pmp28cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp28cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp28cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 28) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 28) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg7].pmp28cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp28cfg & 0x1) == 0) && ((csr_value.pmp28cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp28cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp28cfg; } } - # fall through: keep old value - return CSR[pmpcfg7].pmp28cfg; - pmp29cfg: - location: 15-8 - description: | - *PMP configuration for entry 29* + } + # fall through: keep old value + return CSR[pmpcfg7].pmp28cfg; + pmp29cfg: + location: 15-8 + description: | + *PMP configuration for entry 29* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 29) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 29) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg7].pmp29cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp29cfg & 0x1) == 0) && ((csr_value.pmp29cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp29cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp29cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 29) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 29) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg7].pmp29cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp29cfg & 0x1) == 0) && ((csr_value.pmp29cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp29cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp29cfg; } } - # fall through: keep old value - return CSR[pmpcfg7].pmp29cfg; - pmp30cfg: - location: 23-16 - description: | - *PMP configuration for entry 30* + } + # fall through: keep old value + return CSR[pmpcfg7].pmp29cfg; + pmp30cfg: + location: 23-16 + description: | + *PMP configuration for entry 30* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 30) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 30) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg7].pmp30cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp30cfg & 0x1) == 0) && ((csr_value.pmp30cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp30cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp30cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 30) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 30) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg7].pmp30cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp30cfg & 0x1) == 0) && ((csr_value.pmp30cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp30cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp30cfg; } } - # fall through: keep old value - return CSR[pmpcfg7].pmp30cfg; - pmp31cfg: - location: 31-24 - description: | - *PMP configuration for entry 31* + } + # fall through: keep old value + return CSR[pmpcfg7].pmp30cfg; + pmp31cfg: + location: 31-24 + description: | + *PMP configuration for entry 31* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 31) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 31) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg7].pmp31cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp31cfg & 0x1) == 0) && ((csr_value.pmp31cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp31cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp31cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 31) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 31) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg7].pmp31cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp31cfg & 0x1) == 0) && ((csr_value.pmp31cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp31cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp31cfg; } } - # fall through: keep old value - return CSR[pmpcfg7].pmp31cfg; + } + # fall through: keep old value + return CSR[pmpcfg7].pmp31cfg; diff --git a/arch/csr/I/pmpcfg8.yaml b/arch/csr/I/pmpcfg8.yaml index 3f339a2e1..7cb54f73c 100644 --- a/arch/csr/I/pmpcfg8.yaml +++ b/arch/csr/I/pmpcfg8.yaml @@ -4,511 +4,513 @@ -pmpcfg8: - long_name: PMP Configuration Register 8 - address: 0x3A8 - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp32cfg: - location: 7-0 - description: | - *PMP configuration for entry 32* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). +$schema: csr_schema.json# +kind: csr +name: pmpcfg8 +long_name: PMP Configuration Register 8 +address: 0x3A8 +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp32cfg: + location: 7-0 + description: | + *PMP configuration for entry 32* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 32) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 32) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg8].pmp32cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp32cfg & 0x1) == 0) && ((csr_value.pmp32cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp32cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp32cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 32) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 32) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg8].pmp32cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp32cfg & 0x1) == 0) && ((csr_value.pmp32cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp32cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp32cfg; } } - # fall through: keep old value - return CSR[pmpcfg8].pmp32cfg; - pmp33cfg: - location: 15-8 - description: | - *PMP configuration for entry 33* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg8].pmp32cfg; + pmp33cfg: + location: 15-8 + description: | + *PMP configuration for entry 33* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 33) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 33) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg8].pmp33cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp33cfg & 0x1) == 0) && ((csr_value.pmp33cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp33cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp33cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 33) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 33) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg8].pmp33cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp33cfg & 0x1) == 0) && ((csr_value.pmp33cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp33cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp33cfg; } } - # fall through: keep old value - return CSR[pmpcfg8].pmp33cfg; - pmp34cfg: - location: 23-16 - description: | - *PMP configuration for entry 34* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg8].pmp33cfg; + pmp34cfg: + location: 23-16 + description: | + *PMP configuration for entry 34* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 34) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 34) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg8].pmp34cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp34cfg & 0x1) == 0) && ((csr_value.pmp34cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp34cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp34cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 34) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 34) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg8].pmp34cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp34cfg & 0x1) == 0) && ((csr_value.pmp34cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp34cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp34cfg; } } - # fall through: keep old value - return CSR[pmpcfg8].pmp34cfg; - pmp35cfg: - location: 31-24 - description: | - *PMP configuration for entry 35* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg8].pmp34cfg; + pmp35cfg: + location: 31-24 + description: | + *PMP configuration for entry 35* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 35) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 35) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg8].pmp35cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp35cfg & 0x1) == 0) && ((csr_value.pmp35cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp35cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp35cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 35) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 35) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg8].pmp35cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp35cfg & 0x1) == 0) && ((csr_value.pmp35cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp35cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp35cfg; } } - # fall through: keep old value - return CSR[pmpcfg8].pmp35cfg; - pmp36cfg: - location: 39-32 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 36* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 38:37 ! _Reserved_ Writes shall be ignored. - h! A ! 36:35 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg8].pmp35cfg; + pmp36cfg: + location: 39-32 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 36* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 39 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 38:37 ! _Reserved_ Writes shall be ignored. + h! A ! 36:35 + a! Address matching mode. One of: - h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 36) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 36) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg8].pmp36cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp36cfg & 0x1) == 0) && ((csr_value.pmp36cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp36cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp36cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 34 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 33 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 32 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 36) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 36) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg8].pmp36cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp36cfg & 0x1) == 0) && ((csr_value.pmp36cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp36cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp36cfg; } } - # fall through: keep old value - return CSR[pmpcfg8].pmp36cfg; - pmp37cfg: - location: 47-40 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 37* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 46:45 ! _Reserved_ Writes shall be ignored. - h! A ! 44:43 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg8].pmp36cfg; + pmp37cfg: + location: 47-40 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 37* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 47 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 46:45 ! _Reserved_ Writes shall be ignored. + h! A ! 44:43 + a! Address matching mode. One of: - h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 37) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 37) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg8].pmp37cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp37cfg & 0x1) == 0) && ((csr_value.pmp37cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp37cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp37cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 42 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 41 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 40 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 37) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 37) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg8].pmp37cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp37cfg & 0x1) == 0) && ((csr_value.pmp37cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp37cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp37cfg; } } - # fall through: keep old value - return CSR[pmpcfg8].pmp37cfg; - pmp38cfg: - location: 55-48 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 38* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 54:53 ! _Reserved_ Writes shall be ignored. - h! A ! 52:51 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg8].pmp37cfg; + pmp38cfg: + location: 55-48 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 38* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 55 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 54:53 ! _Reserved_ Writes shall be ignored. + h! A ! 52:51 + a! Address matching mode. One of: - h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 38) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 38) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg8].pmp38cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp38cfg & 0x1) == 0) && ((csr_value.pmp38cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp38cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp38cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 50 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 49 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 48 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 38) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 38) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg8].pmp38cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp38cfg & 0x1) == 0) && ((csr_value.pmp38cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp38cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp38cfg; } } - # fall through: keep old value - return CSR[pmpcfg8].pmp38cfg; - pmp39cfg: - location: 63-56 - base: 64 # upper half doesn't exist in RV32 - description: | - *PMP configuration for entry 39* - - The bits are as follows: - - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description - - h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 62:61 ! _Reserved_ Writes shall be ignored. - h! A ! 60:59 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two - - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + } + # fall through: keep old value + return CSR[pmpcfg8].pmp38cfg; + pmp39cfg: + location: 63-56 + base: 64 # upper half doesn't exist in RV32 + description: | + *PMP configuration for entry 39* + + The bits are as follows: + + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description + + h! L ! 63 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 62:61 ! _Reserved_ Writes shall be ignored. + h! A ! 60:59 + a! Address matching mode. One of: - h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== - - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 39) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 39) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg8].pmp39cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp39cfg & 0x1) == 0) && ((csr_value.pmp39cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp39cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp39cfg; - } + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two + + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 58 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 57 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 56 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== + + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 39) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 39) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg8].pmp39cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp39cfg & 0x1) == 0) && ((csr_value.pmp39cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp39cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp39cfg; } } - # fall through: keep old value - return CSR[pmpcfg8].pmp39cfg; + } + # fall through: keep old value + return CSR[pmpcfg8].pmp39cfg; diff --git a/arch/csr/I/pmpcfg9.yaml b/arch/csr/I/pmpcfg9.yaml index 768794a7e..d8daa4a91 100644 --- a/arch/csr/I/pmpcfg9.yaml +++ b/arch/csr/I/pmpcfg9.yaml @@ -4,260 +4,262 @@ -pmpcfg9: - base: 32 # odd numbered pmpcfg registers do not exist in RV64 - long_name: PMP Configuration Register 9 - address: 0x3A9 - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - pmp36cfg: - location: 7-0 - description: | - *PMP configuration for entry 36* +$schema: csr_schema.json# +kind: csr +name: pmpcfg9 +base: 32 # odd numbered pmpcfg registers do not exist in RV64 +long_name: PMP Configuration Register 9 +address: 0x3A9 +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + pmp36cfg: + location: 7-0 + description: | + *PMP configuration for entry 36* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 6:5 ! _Reserved_ Writes shall be ignored. - h! A ! 4:3 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 7 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 6:5 ! _Reserved_ Writes shall be ignored. + h! A ! 4:3 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 2 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 1 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 0 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 36) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 36) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg9].pmp36cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp36cfg & 0x1) == 0) && ((csr_value.pmp36cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp36cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp36cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 36) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 36) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg9].pmp36cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp36cfg & 0x1) == 0) && ((csr_value.pmp36cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp36cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp36cfg; } } - # fall through: keep old value - return CSR[pmpcfg9].pmp36cfg; - pmp37cfg: - location: 15-8 - description: | - *PMP configuration for entry 37* + } + # fall through: keep old value + return CSR[pmpcfg9].pmp36cfg; + pmp37cfg: + location: 15-8 + description: | + *PMP configuration for entry 37* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 14:13 ! _Reserved_ Writes shall be ignored. - h! A ! 12:11 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 15 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 14:13 ! _Reserved_ Writes shall be ignored. + h! A ! 12:11 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 10 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 9 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 8 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 37) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 37) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg9].pmp37cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp37cfg & 0x1) == 0) && ((csr_value.pmp37cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp37cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp37cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 37) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 37) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg9].pmp37cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp37cfg & 0x1) == 0) && ((csr_value.pmp37cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp37cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp37cfg; } } - # fall through: keep old value - return CSR[pmpcfg9].pmp37cfg; - pmp38cfg: - location: 23-16 - description: | - *PMP configuration for entry 38* + } + # fall through: keep old value + return CSR[pmpcfg9].pmp37cfg; + pmp38cfg: + location: 23-16 + description: | + *PMP configuration for entry 38* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 22:21 ! _Reserved_ Writes shall be ignored. - h! A ! 20:19 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 23 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 22:21 ! _Reserved_ Writes shall be ignored. + h! A ! 20:19 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 18 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 17 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 16 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 38) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 38) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg9].pmp38cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp38cfg & 0x1) == 0) && ((csr_value.pmp38cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp38cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp38cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 38) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 38) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg9].pmp38cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp38cfg & 0x1) == 0) && ((csr_value.pmp38cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp38cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp38cfg; } } - # fall through: keep old value - return CSR[pmpcfg9].pmp38cfg; - pmp39cfg: - location: 31-24 - description: | - *PMP configuration for entry 39* + } + # fall through: keep old value + return CSR[pmpcfg9].pmp38cfg; + pmp39cfg: + location: 31-24 + description: | + *PMP configuration for entry 39* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! 30:29 ! _Reserved_ Writes shall be ignored. - h! A ! 28:27 - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! 31 ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! 30:29 ! _Reserved_ Writes shall be ignored. + h! A ! 28:27 + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! 26 ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! 25 ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! 24 ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > 39) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > 39) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[pmpcfg9].pmp39cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp39cfg & 0x1) == 0) && ((csr_value.pmp39cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp39cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp39cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > 39) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > 39) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[pmpcfg9].pmp39cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp39cfg & 0x1) == 0) && ((csr_value.pmp39cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp39cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp39cfg; } } - # fall through: keep old value - return CSR[pmpcfg9].pmp39cfg; + } + # fall through: keep old value + return CSR[pmpcfg9].pmp39cfg; diff --git a/arch/csr/I/pmpcfgN.layout b/arch/csr/I/pmpcfgN.layout index da1dd4a85..9c76a61fc 100644 --- a/arch/csr/I/pmpcfgN.layout +++ b/arch/csr/I/pmpcfgN.layout @@ -2,81 +2,83 @@ <%- raise "'pmpcfg_num' must be defined" if pmpcfg_num.nil? -%> -pmpcfg<%= pmpcfg_num %>: - <%- if pmpcfg_num.odd? -%> - base: 32 # odd numbered pmpcfg registers do not exist in RV64 - <%- end -%> - long_name: PMP Configuration Register <%= pmpcfg_num %> - address: 0x<%= (0x3A0 + pmpcfg_num).to_s(16).upcase %> - priv_mode: M - length: MXLEN - description: PMP entry configuration - definedBy: Smpmp - fields: - <%- (pmpcfg_num.odd? ? 4 : 8).times do |i| -%> - pmp<%= pmpcfg_num*4 + i %>cfg: - location: <%= ((i+1)*8)-1 %>-<%= i*8 %> - <%- if i >= 4 -%> - base: 64 # upper half doesn't exist in RV32 - <%- end -%> - description: | - *PMP configuration for entry <%= pmpcfg_num*4 + i %>* +$schema: csr_schema.json# +kind: csr +name: pmpcfg<%= pmpcfg_num %> +<%- if pmpcfg_num.odd? -%> +base: 32 # odd numbered pmpcfg registers do not exist in RV64 +<%- end -%> +long_name: PMP Configuration Register <%= pmpcfg_num %> +address: 0x<%= (0x3A0 + pmpcfg_num).to_s(16).upcase %> +priv_mode: M +length: MXLEN +description: PMP entry configuration +definedBy: Smpmp +fields: + <%- (pmpcfg_num.odd? ? 4 : 8).times do |i| -%> + pmp<%= pmpcfg_num*4 + i %>cfg: + location: <%= ((i+1)*8)-1 %>-<%= i*8 %> + <%- if i >= 4 -%> + base: 64 # upper half doesn't exist in RV32 + <%- end -%> + description: | + *PMP configuration for entry <%= pmpcfg_num*4 + i %>* - The bits are as follows: + The bits are as follows: - [separator="!",%autowidth] - !=== - ! Name ! Location ! Description + [separator="!",%autowidth] + !=== + ! Name ! Location ! Description - h! L ! <%= ((i+1)*8)-1 %> ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. - h! - ! <%= ((i+1)*8)-2 %>:<%= ((i+1)*8)-3 %> ! _Reserved_ Writes shall be ignored. - h! A ! <%= ((i+1)*8)-4 %>:<%= ((i+1)*8)-5 %> - a! Address matching mode. One of: - - [when="PMP_GRANULARITY < 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NA4* (2) - Naturally aligned four-byte region - * *NAPOT* (3) - Natrually aligned power of two + h! L ! <%= ((i+1)*8)-1 %> ! Locks the entry from further modification. Additionally, when set, PMP checks also apply to M-mode for the entry. + h! - ! <%= ((i+1)*8)-2 %>:<%= ((i+1)*8)-3 %> ! _Reserved_ Writes shall be ignored. + h! A ! <%= ((i+1)*8)-4 %>:<%= ((i+1)*8)-5 %> + a! Address matching mode. One of: + + [when="PMP_GRANULARITY < 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NA4* (2) - Naturally aligned four-byte region + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - * *OFF* (0) - Null region (disabled) - * *TOR* (1) - Top of range - * *NAPOT* (3) - Natrually aligned power of two + [when="PMP_GRANULARITY >= 2"] + * *OFF* (0) - Null region (disabled) + * *TOR* (1) - Top of range + * *NAPOT* (3) - Natrually aligned power of two - [when="PMP_GRANULARITY >= 2"] - Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). - - h! X ! <%= ((i)*8)+2 %> ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. - h! W ! <%= ((i)*8)+1 %> ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. - h! R ! <%= ((i)*8)+0 %> ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. - !=== + [when="PMP_GRANULARITY >= 2"] + Naturally aligned four-byte region, *NA4* (2), is not valid (not needed when the PMP granularity is larger than 4 bytes). + + h! X ! <%= ((i)*8)+2 %> ! When clear, instruction fetchs cause an `Access Fault` for the matching region and privilege mode. + h! W ! <%= ((i)*8)+1 %> ! When clear, stores and AMOs cause an `Access Fault` for the matching region and privilege mode. + h! R ! <%= ((i)*8)+0 %> ! When clear, loads cause an `Access Fault` for the matching region and privilege mode. + !=== - The combination of R = 0, W = 1 is reserved. - type(): | - if (NUM_PMP_ENTRIES > <%= pmpcfg_num*4 + i %>) { - return CsrFieldType::RWR; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (NUM_PMP_ENTRIES > <%= pmpcfg_num*4 + i %>) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if ((CSR[<%= "pmpcfg#{pmpcfg_num}" %>].pmp<%= pmpcfg_num*4 + i %>cfg & 0x80) == 0) { - # entry is not locked - if (!(((csr_value.pmp<%= pmpcfg_num*4 + i %>cfg & 0x1) == 0) && ((csr_value.pmp<%= pmpcfg_num*4 + i %>cfg & 0x2) == 0x2))) { - # not R = 0, W =1, which is reserved - if ((PMP_GRANULARITY < 2) || - ((csr_value.pmp<%= pmpcfg_num*4 + i %>cfg & 0x18) != 0x10)) { - # NA4 is not allowed when PMP granularity is larger than 4 bytes - return csr_value.pmp<%= pmpcfg_num*4 + i %>cfg; - } + The combination of R = 0, W = 1 is reserved. + type(): | + if (NUM_PMP_ENTRIES > <%= pmpcfg_num*4 + i %>) { + return CsrFieldType::RWR; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (NUM_PMP_ENTRIES > <%= pmpcfg_num*4 + i %>) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if ((CSR[<%= "pmpcfg#{pmpcfg_num}" %>].pmp<%= pmpcfg_num*4 + i %>cfg & 0x80) == 0) { + # entry is not locked + if (!(((csr_value.pmp<%= pmpcfg_num*4 + i %>cfg & 0x1) == 0) && ((csr_value.pmp<%= pmpcfg_num*4 + i %>cfg & 0x2) == 0x2))) { + # not R = 0, W =1, which is reserved + if ((PMP_GRANULARITY < 2) || + ((csr_value.pmp<%= pmpcfg_num*4 + i %>cfg & 0x18) != 0x10)) { + # NA4 is not allowed when PMP granularity is larger than 4 bytes + return csr_value.pmp<%= pmpcfg_num*4 + i %>cfg; } } - # fall through: keep old value - return CSR[<%= "pmpcfg#{pmpcfg_num}" %>].pmp<%= pmpcfg_num*4 + i %>cfg; - <%- end -%> + } + # fall through: keep old value + return CSR[<%= "pmpcfg#{pmpcfg_num}" %>].pmp<%= pmpcfg_num*4 + i %>cfg; + <%- end -%> diff --git a/arch/csr/S/scounteren.layout b/arch/csr/S/scounteren.layout index eecf21dbf..6a98b50ce 100644 --- a/arch/csr/S/scounteren.layout +++ b/arch/csr/S/scounteren.layout @@ -1,87 +1,89 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -scounteren: - long_name: Supervisor Counter Enable - address: 0x106 - priv_mode: S - length: 32 - description: | - Delegates control of the hardware performance-monitoring counters - to U-mode - definedBy: S - fields: - CY: - location: 0 - description: | - When both `scounteren.CY` and `mcounteren.CY` are set, the `cycle` CSR (an alias of `mcycle`) is accessible to U-mode - <%% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.CY`)<%% end %>. - definedBy: Zicntr - type(): | - if (SCOUNTENABLE_EN[0]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[0]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - TM: - location: 1 - description: | - When both `scounteren.TM` and `mcounteren.TM` are set, the `time` CSR (an alias of `mtime` memory-mapped CSR) is accessible to U-mode - <%% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.TM`)<%% end %>. - definedBy: Zicntr - type(): | - if (SCOUNTENABLE_EN[1]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[1]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - IR: - location: 2 - description: | - When both `scounteren.IR` and `mcounteren.IR` are set, the `instret` CSR (an alias of memory-mapped `minstret`) is accessible to U-mode - <%% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.IR`)<%% end %>. - definedBy: Zicntr - type(): | - if (SCOUNTENABLE_EN[2]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[2]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - <%- (3..31).each do |hpm_num| -%> - HPM<%= hpm_num %>: - location: <%= hpm_num %> - description: | - When both `scounteren.HPM<%= hpm_num %>` and `mcounteren.HPM<%= hpm_num %>` are set, the `hpmcounter<%= hpm_num %>` CSR (an alias of `mhpmcounter<%= hpm_num %>`) - is accessible to U-mode - <%% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM<%= hpm_num %>`)<%% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[<%= hpm_num %>]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[<%= hpm_num %>]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - <%- end -%> +$schema: csr_schema.json# +kind: csr +name: scounteren +long_name: Supervisor Counter Enable +address: 0x106 +priv_mode: S +length: 32 +description: | + Delegates control of the hardware performance-monitoring counters + to U-mode +definedBy: S +fields: + CY: + location: 0 + description: | + When both `scounteren.CY` and `mcounteren.CY` are set, the `cycle` CSR (an alias of `mcycle`) is accessible to U-mode + <%% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.CY`)<%% end %>. + definedBy: Zicntr + type(): | + if (SCOUNTENABLE_EN[0]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[0]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + TM: + location: 1 + description: | + When both `scounteren.TM` and `mcounteren.TM` are set, the `time` CSR (an alias of `mtime` memory-mapped CSR) is accessible to U-mode + <%% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.TM`)<%% end %>. + definedBy: Zicntr + type(): | + if (SCOUNTENABLE_EN[1]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[1]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + IR: + location: 2 + description: | + When both `scounteren.IR` and `mcounteren.IR` are set, the `instret` CSR (an alias of memory-mapped `minstret`) is accessible to U-mode + <%% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.IR`)<%% end %>. + definedBy: Zicntr + type(): | + if (SCOUNTENABLE_EN[2]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[2]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + <%- (3..31).each do |hpm_num| -%> + HPM<%= hpm_num %>: + location: <%= hpm_num %> + description: | + When both `scounteren.HPM<%= hpm_num %>` and `mcounteren.HPM<%= hpm_num %>` are set, the `hpmcounter<%= hpm_num %>` CSR (an alias of `mhpmcounter<%= hpm_num %>`) + is accessible to U-mode + <%% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM<%= hpm_num %>`)<%% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[<%= hpm_num %>]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[<%= hpm_num %>]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + <%- end -%> diff --git a/arch/csr/S/scounteren.yaml b/arch/csr/S/scounteren.yaml index 385d53997..f0055805a 100644 --- a/arch/csr/S/scounteren.yaml +++ b/arch/csr/S/scounteren.yaml @@ -3,618 +3,620 @@ # WARNING: This file is auto-generated from arch/csr/S/scounteren.layout -scounteren: - long_name: Supervisor Counter Enable - address: 0x106 - priv_mode: S - length: 32 - description: | - Delegates control of the hardware performance-monitoring counters - to U-mode - definedBy: S - fields: - CY: - location: 0 - description: | - When both `scounteren.CY` and `mcounteren.CY` are set, the `cycle` CSR (an alias of `mcycle`) is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.CY`)<% end %>. - definedBy: Zicntr - type(): | - if (SCOUNTENABLE_EN[0]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[0]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - TM: - location: 1 - description: | - When both `scounteren.TM` and `mcounteren.TM` are set, the `time` CSR (an alias of `mtime` memory-mapped CSR) is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.TM`)<% end %>. - definedBy: Zicntr - type(): | - if (SCOUNTENABLE_EN[1]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[1]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - IR: - location: 2 - description: | - When both `scounteren.IR` and `mcounteren.IR` are set, the `instret` CSR (an alias of memory-mapped `minstret`) is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.IR`)<% end %>. - definedBy: Zicntr - type(): | - if (SCOUNTENABLE_EN[2]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[2]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM3: - location: 3 - description: | - When both `scounteren.HPM3` and `mcounteren.HPM3` are set, the `hpmcounter3` CSR (an alias of `mhpmcounter3`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM3`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[3]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[3]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM4: - location: 4 - description: | - When both `scounteren.HPM4` and `mcounteren.HPM4` are set, the `hpmcounter4` CSR (an alias of `mhpmcounter4`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM4`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[4]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[4]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM5: - location: 5 - description: | - When both `scounteren.HPM5` and `mcounteren.HPM5` are set, the `hpmcounter5` CSR (an alias of `mhpmcounter5`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM5`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[5]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[5]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM6: - location: 6 - description: | - When both `scounteren.HPM6` and `mcounteren.HPM6` are set, the `hpmcounter6` CSR (an alias of `mhpmcounter6`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM6`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[6]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[6]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM7: - location: 7 - description: | - When both `scounteren.HPM7` and `mcounteren.HPM7` are set, the `hpmcounter7` CSR (an alias of `mhpmcounter7`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM7`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[7]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[7]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM8: - location: 8 - description: | - When both `scounteren.HPM8` and `mcounteren.HPM8` are set, the `hpmcounter8` CSR (an alias of `mhpmcounter8`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM8`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[8]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[8]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM9: - location: 9 - description: | - When both `scounteren.HPM9` and `mcounteren.HPM9` are set, the `hpmcounter9` CSR (an alias of `mhpmcounter9`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM9`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[9]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[9]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM10: - location: 10 - description: | - When both `scounteren.HPM10` and `mcounteren.HPM10` are set, the `hpmcounter10` CSR (an alias of `mhpmcounter10`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM10`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[10]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[10]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM11: - location: 11 - description: | - When both `scounteren.HPM11` and `mcounteren.HPM11` are set, the `hpmcounter11` CSR (an alias of `mhpmcounter11`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM11`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[11]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[11]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM12: - location: 12 - description: | - When both `scounteren.HPM12` and `mcounteren.HPM12` are set, the `hpmcounter12` CSR (an alias of `mhpmcounter12`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM12`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[12]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[12]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM13: - location: 13 - description: | - When both `scounteren.HPM13` and `mcounteren.HPM13` are set, the `hpmcounter13` CSR (an alias of `mhpmcounter13`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM13`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[13]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[13]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM14: - location: 14 - description: | - When both `scounteren.HPM14` and `mcounteren.HPM14` are set, the `hpmcounter14` CSR (an alias of `mhpmcounter14`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM14`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[14]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[14]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM15: - location: 15 - description: | - When both `scounteren.HPM15` and `mcounteren.HPM15` are set, the `hpmcounter15` CSR (an alias of `mhpmcounter15`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM15`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[15]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[15]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM16: - location: 16 - description: | - When both `scounteren.HPM16` and `mcounteren.HPM16` are set, the `hpmcounter16` CSR (an alias of `mhpmcounter16`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM16`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[16]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[16]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM17: - location: 17 - description: | - When both `scounteren.HPM17` and `mcounteren.HPM17` are set, the `hpmcounter17` CSR (an alias of `mhpmcounter17`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM17`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[17]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[17]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM18: - location: 18 - description: | - When both `scounteren.HPM18` and `mcounteren.HPM18` are set, the `hpmcounter18` CSR (an alias of `mhpmcounter18`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM18`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[18]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[18]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM19: - location: 19 - description: | - When both `scounteren.HPM19` and `mcounteren.HPM19` are set, the `hpmcounter19` CSR (an alias of `mhpmcounter19`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM19`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[19]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[19]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM20: - location: 20 - description: | - When both `scounteren.HPM20` and `mcounteren.HPM20` are set, the `hpmcounter20` CSR (an alias of `mhpmcounter20`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM20`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[20]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[20]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM21: - location: 21 - description: | - When both `scounteren.HPM21` and `mcounteren.HPM21` are set, the `hpmcounter21` CSR (an alias of `mhpmcounter21`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM21`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[21]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[21]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM22: - location: 22 - description: | - When both `scounteren.HPM22` and `mcounteren.HPM22` are set, the `hpmcounter22` CSR (an alias of `mhpmcounter22`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM22`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[22]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[22]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM23: - location: 23 - description: | - When both `scounteren.HPM23` and `mcounteren.HPM23` are set, the `hpmcounter23` CSR (an alias of `mhpmcounter23`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM23`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[23]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[23]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM24: - location: 24 - description: | - When both `scounteren.HPM24` and `mcounteren.HPM24` are set, the `hpmcounter24` CSR (an alias of `mhpmcounter24`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM24`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[24]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[24]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM25: - location: 25 - description: | - When both `scounteren.HPM25` and `mcounteren.HPM25` are set, the `hpmcounter25` CSR (an alias of `mhpmcounter25`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM25`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[25]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[25]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM26: - location: 26 - description: | - When both `scounteren.HPM26` and `mcounteren.HPM26` are set, the `hpmcounter26` CSR (an alias of `mhpmcounter26`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM26`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[26]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[26]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM27: - location: 27 - description: | - When both `scounteren.HPM27` and `mcounteren.HPM27` are set, the `hpmcounter27` CSR (an alias of `mhpmcounter27`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM27`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[27]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[27]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM28: - location: 28 - description: | - When both `scounteren.HPM28` and `mcounteren.HPM28` are set, the `hpmcounter28` CSR (an alias of `mhpmcounter28`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM28`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[28]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[28]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM29: - location: 29 - description: | - When both `scounteren.HPM29` and `mcounteren.HPM29` are set, the `hpmcounter29` CSR (an alias of `mhpmcounter29`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM29`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[29]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[29]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM30: - location: 30 - description: | - When both `scounteren.HPM30` and `mcounteren.HPM30` are set, the `hpmcounter30` CSR (an alias of `mhpmcounter30`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM30`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[30]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[30]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - HPM31: - location: 31 - description: | - When both `scounteren.HPM31` and `mcounteren.HPM31` are set, the `hpmcounter31` CSR (an alias of `mhpmcounter31`) - is accessible to U-mode - <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM31`)<% end %>. - definedBy: Zihpm - type(): | - if (SCOUNTENABLE_EN[31]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (SCOUNTENABLE_EN[31]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: scounteren +long_name: Supervisor Counter Enable +address: 0x106 +priv_mode: S +length: 32 +description: | + Delegates control of the hardware performance-monitoring counters + to U-mode +definedBy: S +fields: + CY: + location: 0 + description: | + When both `scounteren.CY` and `mcounteren.CY` are set, the `cycle` CSR (an alias of `mcycle`) is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.CY`)<% end %>. + definedBy: Zicntr + type(): | + if (SCOUNTENABLE_EN[0]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[0]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + TM: + location: 1 + description: | + When both `scounteren.TM` and `mcounteren.TM` are set, the `time` CSR (an alias of `mtime` memory-mapped CSR) is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.TM`)<% end %>. + definedBy: Zicntr + type(): | + if (SCOUNTENABLE_EN[1]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[1]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + IR: + location: 2 + description: | + When both `scounteren.IR` and `mcounteren.IR` are set, the `instret` CSR (an alias of memory-mapped `minstret`) is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.IR`)<% end %>. + definedBy: Zicntr + type(): | + if (SCOUNTENABLE_EN[2]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[2]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM3: + location: 3 + description: | + When both `scounteren.HPM3` and `mcounteren.HPM3` are set, the `hpmcounter3` CSR (an alias of `mhpmcounter3`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM3`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[3]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[3]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM4: + location: 4 + description: | + When both `scounteren.HPM4` and `mcounteren.HPM4` are set, the `hpmcounter4` CSR (an alias of `mhpmcounter4`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM4`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[4]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[4]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM5: + location: 5 + description: | + When both `scounteren.HPM5` and `mcounteren.HPM5` are set, the `hpmcounter5` CSR (an alias of `mhpmcounter5`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM5`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[5]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[5]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM6: + location: 6 + description: | + When both `scounteren.HPM6` and `mcounteren.HPM6` are set, the `hpmcounter6` CSR (an alias of `mhpmcounter6`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM6`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[6]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[6]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM7: + location: 7 + description: | + When both `scounteren.HPM7` and `mcounteren.HPM7` are set, the `hpmcounter7` CSR (an alias of `mhpmcounter7`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM7`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[7]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[7]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM8: + location: 8 + description: | + When both `scounteren.HPM8` and `mcounteren.HPM8` are set, the `hpmcounter8` CSR (an alias of `mhpmcounter8`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM8`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[8]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[8]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM9: + location: 9 + description: | + When both `scounteren.HPM9` and `mcounteren.HPM9` are set, the `hpmcounter9` CSR (an alias of `mhpmcounter9`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM9`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[9]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[9]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM10: + location: 10 + description: | + When both `scounteren.HPM10` and `mcounteren.HPM10` are set, the `hpmcounter10` CSR (an alias of `mhpmcounter10`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM10`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[10]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[10]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM11: + location: 11 + description: | + When both `scounteren.HPM11` and `mcounteren.HPM11` are set, the `hpmcounter11` CSR (an alias of `mhpmcounter11`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM11`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[11]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[11]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM12: + location: 12 + description: | + When both `scounteren.HPM12` and `mcounteren.HPM12` are set, the `hpmcounter12` CSR (an alias of `mhpmcounter12`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM12`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[12]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[12]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM13: + location: 13 + description: | + When both `scounteren.HPM13` and `mcounteren.HPM13` are set, the `hpmcounter13` CSR (an alias of `mhpmcounter13`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM13`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[13]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[13]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM14: + location: 14 + description: | + When both `scounteren.HPM14` and `mcounteren.HPM14` are set, the `hpmcounter14` CSR (an alias of `mhpmcounter14`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM14`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[14]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[14]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM15: + location: 15 + description: | + When both `scounteren.HPM15` and `mcounteren.HPM15` are set, the `hpmcounter15` CSR (an alias of `mhpmcounter15`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM15`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[15]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[15]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM16: + location: 16 + description: | + When both `scounteren.HPM16` and `mcounteren.HPM16` are set, the `hpmcounter16` CSR (an alias of `mhpmcounter16`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM16`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[16]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[16]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM17: + location: 17 + description: | + When both `scounteren.HPM17` and `mcounteren.HPM17` are set, the `hpmcounter17` CSR (an alias of `mhpmcounter17`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM17`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[17]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[17]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM18: + location: 18 + description: | + When both `scounteren.HPM18` and `mcounteren.HPM18` are set, the `hpmcounter18` CSR (an alias of `mhpmcounter18`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM18`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[18]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[18]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM19: + location: 19 + description: | + When both `scounteren.HPM19` and `mcounteren.HPM19` are set, the `hpmcounter19` CSR (an alias of `mhpmcounter19`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM19`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[19]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[19]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM20: + location: 20 + description: | + When both `scounteren.HPM20` and `mcounteren.HPM20` are set, the `hpmcounter20` CSR (an alias of `mhpmcounter20`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM20`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[20]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[20]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM21: + location: 21 + description: | + When both `scounteren.HPM21` and `mcounteren.HPM21` are set, the `hpmcounter21` CSR (an alias of `mhpmcounter21`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM21`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[21]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[21]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM22: + location: 22 + description: | + When both `scounteren.HPM22` and `mcounteren.HPM22` are set, the `hpmcounter22` CSR (an alias of `mhpmcounter22`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM22`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[22]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[22]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM23: + location: 23 + description: | + When both `scounteren.HPM23` and `mcounteren.HPM23` are set, the `hpmcounter23` CSR (an alias of `mhpmcounter23`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM23`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[23]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[23]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM24: + location: 24 + description: | + When both `scounteren.HPM24` and `mcounteren.HPM24` are set, the `hpmcounter24` CSR (an alias of `mhpmcounter24`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM24`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[24]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[24]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM25: + location: 25 + description: | + When both `scounteren.HPM25` and `mcounteren.HPM25` are set, the `hpmcounter25` CSR (an alias of `mhpmcounter25`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM25`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[25]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[25]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM26: + location: 26 + description: | + When both `scounteren.HPM26` and `mcounteren.HPM26` are set, the `hpmcounter26` CSR (an alias of `mhpmcounter26`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM26`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[26]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[26]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM27: + location: 27 + description: | + When both `scounteren.HPM27` and `mcounteren.HPM27` are set, the `hpmcounter27` CSR (an alias of `mhpmcounter27`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM27`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[27]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[27]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM28: + location: 28 + description: | + When both `scounteren.HPM28` and `mcounteren.HPM28` are set, the `hpmcounter28` CSR (an alias of `mhpmcounter28`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM28`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[28]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[28]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM29: + location: 29 + description: | + When both `scounteren.HPM29` and `mcounteren.HPM29` are set, the `hpmcounter29` CSR (an alias of `mhpmcounter29`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM29`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[29]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[29]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM30: + location: 30 + description: | + When both `scounteren.HPM30` and `mcounteren.HPM30` are set, the `hpmcounter30` CSR (an alias of `mhpmcounter30`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM30`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[30]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[30]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + HPM31: + location: 31 + description: | + When both `scounteren.HPM31` and `mcounteren.HPM31` are set, the `hpmcounter31` CSR (an alias of `mhpmcounter31`) + is accessible to U-mode + <% if ext?(:H) %>(delegation to VS/VU mode is further handled by `hcounteren.HPM31`)<% end %>. + definedBy: Zihpm + type(): | + if (SCOUNTENABLE_EN[31]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (SCOUNTENABLE_EN[31]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zicntr/mcountinhibit.layout b/arch/csr/Zicntr/mcountinhibit.layout index 9fe4b431a..01d8a4bce 100644 --- a/arch/csr/Zicntr/mcountinhibit.layout +++ b/arch/csr/Zicntr/mcountinhibit.layout @@ -1,75 +1,77 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mcountinhibit: - long_name: Machine Counter Inhibit - address: 0x320 - priv_mode: M - length: 32 - description: | - Bits to inhibit (stops counting) performance counters. +$schema: csr_schema.json# +kind: csr +name: mcountinhibit +long_name: Machine Counter Inhibit +address: 0x320 +priv_mode: M +length: 32 +description: | + Bits to inhibit (stops counting) performance counters. - The counter-inhibit register `mcountinhibit` is a *WARL* register that - controls which of the hardware performance-monitoring counters - increment. The settings in this register only control whether the - counters increment; their accessibility is not affected by the setting - of this register. + The counter-inhibit register `mcountinhibit` is a *WARL* register that + controls which of the hardware performance-monitoring counters + increment. The settings in this register only control whether the + counters increment; their accessibility is not affected by the setting + of this register. - When the CY, IR, or HPM__n__ bit in the `mcountinhibit` register is clear, - the `mcycle`, `minstret`, or `mhpmcountern` register increments as usual. - When the CY, IR, or HPM_n_ bit is set, the corresponding counter does - not increment. + When the CY, IR, or HPM__n__ bit in the `mcountinhibit` register is clear, + the `mcycle`, `minstret`, or `mhpmcountern` register increments as usual. + When the CY, IR, or HPM_n_ bit is set, the corresponding counter does + not increment. - The `mcycle` CSR may be shared between harts on the same core, in which - case the `mcountinhibit.CY` field is also shared between those harts, - and so writes to `mcountinhibit.CY` will be visible to those harts. + The `mcycle` CSR may be shared between harts on the same core, in which + case the `mcountinhibit.CY` field is also shared between those harts, + and so writes to `mcountinhibit.CY` will be visible to those harts. - If the `mcountinhibit` register is not implemented, the implementation - behaves as though the register were set to zero. + If the `mcountinhibit` register is not implemented, the implementation + behaves as though the register were set to zero. - [NOTE] - ==== - When the `mcycle` and `minstret` counters are not needed, it is desirable - to conditionally inhibit them to reduce energy consumption. Providing a - single CSR to inhibit all counters also allows the counters to be - atomically sampled. + [NOTE] + ==== + When the `mcycle` and `minstret` counters are not needed, it is desirable + to conditionally inhibit them to reduce energy consumption. Providing a + single CSR to inhibit all counters also allows the counters to be + atomically sampled. - Because the `mtime` counter can be shared between multiple cores, it - cannot be inhibited with the `mcountinhibit` mechanism. - ==== + Because the `mtime` counter can be shared between multiple cores, it + cannot be inhibited with the `mcountinhibit` mechanism. + ==== - definedBy: - anyOf: - - name: Sm - - name: Smhpm - fields: - CY: - location: 0 - definedBy: Sm - description: When set, `mcycle.COUNT` stops counting in all privilege modes. - type(): | - return COUNTINHIBIT_EN[0] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[0] ? UNDEFINED_LEGAL : 0; - IR: - location: 2 - definedBy: Sm - description: When set, `minstret.COUNT` stops counting in all privilege modes. - type(): | - return COUNTINHIBIT_EN[2] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[2] ? UNDEFINED_LEGAL : 0; - <%- (3..31).each do |hpm_num| -%> - HPM<%= hpm_num %>: - location: <%= hpm_num %> - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[<%= hpm_num %>] == true"] - When set, `hpmcounter<%= hpm_num %>.COUNT` stops counting in all privilege modes. +definedBy: + anyOf: + - name: Sm + - name: Smhpm +fields: + CY: + location: 0 + definedBy: Sm + description: When set, `mcycle.COUNT` stops counting in all privilege modes. + type(): | + return COUNTINHIBIT_EN[0] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[0] ? UNDEFINED_LEGAL : 0; + IR: + location: 2 + definedBy: Sm + description: When set, `minstret.COUNT` stops counting in all privilege modes. + type(): | + return COUNTINHIBIT_EN[2] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[2] ? UNDEFINED_LEGAL : 0; + <%- (3..31).each do |hpm_num| -%> + HPM<%= hpm_num %>: + location: <%= hpm_num %> + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[<%= hpm_num %>] == true"] + When set, `hpmcounter<%= hpm_num %>.COUNT` stops counting in all privilege modes. - [when="COUNTINHIBIT_EN[<%= hpm_num %>] == false"] - Since hpmcounter<%= hpm_num %> is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[<%= hpm_num %>] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[<%= hpm_num %>] ? UNDEFINED_LEGAL : 0; - <%- end -%> \ No newline at end of file + [when="COUNTINHIBIT_EN[<%= hpm_num %>] == false"] + Since hpmcounter<%= hpm_num %> is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[<%= hpm_num %>] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[<%= hpm_num %>] ? UNDEFINED_LEGAL : 0; + <%- end -%> \ No newline at end of file diff --git a/arch/csr/Zicntr/mcountinhibit.yaml b/arch/csr/Zicntr/mcountinhibit.yaml index 6d3f1e595..a8d3fe823 100644 --- a/arch/csr/Zicntr/mcountinhibit.yaml +++ b/arch/csr/Zicntr/mcountinhibit.yaml @@ -3,438 +3,440 @@ # WARNING: This file is auto-generated from arch/csr/Zicntr/mcountinhibit.layout -mcountinhibit: - long_name: Machine Counter Inhibit - address: 0x320 - priv_mode: M - length: 32 - description: | - Bits to inhibit (stops counting) performance counters. - - The counter-inhibit register `mcountinhibit` is a *WARL* register that - controls which of the hardware performance-monitoring counters - increment. The settings in this register only control whether the - counters increment; their accessibility is not affected by the setting - of this register. - - When the CY, IR, or HPM__n__ bit in the `mcountinhibit` register is clear, - the `mcycle`, `minstret`, or `mhpmcountern` register increments as usual. - When the CY, IR, or HPM_n_ bit is set, the corresponding counter does - not increment. - - The `mcycle` CSR may be shared between harts on the same core, in which - case the `mcountinhibit.CY` field is also shared between those harts, - and so writes to `mcountinhibit.CY` will be visible to those harts. - - If the `mcountinhibit` register is not implemented, the implementation - behaves as though the register were set to zero. - - [NOTE] - ==== - When the `mcycle` and `minstret` counters are not needed, it is desirable - to conditionally inhibit them to reduce energy consumption. Providing a - single CSR to inhibit all counters also allows the counters to be - atomically sampled. - - Because the `mtime` counter can be shared between multiple cores, it - cannot be inhibited with the `mcountinhibit` mechanism. - ==== - - definedBy: - anyOf: - - name: Sm - - name: Smhpm - fields: - CY: - location: 0 - definedBy: Sm - description: When set, `mcycle.COUNT` stops counting in all privilege modes. - type(): | - return COUNTINHIBIT_EN[0] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[0] ? UNDEFINED_LEGAL : 0; - IR: - location: 2 - definedBy: Sm - description: When set, `minstret.COUNT` stops counting in all privilege modes. - type(): | - return COUNTINHIBIT_EN[2] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[2] ? UNDEFINED_LEGAL : 0; - HPM3: - location: 3 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[3] == true"] - When set, `hpmcounter3.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[3] == false"] - Since hpmcounter3 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[3] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[3] ? UNDEFINED_LEGAL : 0; - HPM4: - location: 4 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[4] == true"] - When set, `hpmcounter4.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[4] == false"] - Since hpmcounter4 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[4] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[4] ? UNDEFINED_LEGAL : 0; - HPM5: - location: 5 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[5] == true"] - When set, `hpmcounter5.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[5] == false"] - Since hpmcounter5 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[5] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[5] ? UNDEFINED_LEGAL : 0; - HPM6: - location: 6 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[6] == true"] - When set, `hpmcounter6.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[6] == false"] - Since hpmcounter6 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[6] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[6] ? UNDEFINED_LEGAL : 0; - HPM7: - location: 7 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[7] == true"] - When set, `hpmcounter7.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[7] == false"] - Since hpmcounter7 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[7] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[7] ? UNDEFINED_LEGAL : 0; - HPM8: - location: 8 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[8] == true"] - When set, `hpmcounter8.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[8] == false"] - Since hpmcounter8 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[8] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[8] ? UNDEFINED_LEGAL : 0; - HPM9: - location: 9 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[9] == true"] - When set, `hpmcounter9.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[9] == false"] - Since hpmcounter9 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[9] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[9] ? UNDEFINED_LEGAL : 0; - HPM10: - location: 10 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[10] == true"] - When set, `hpmcounter10.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[10] == false"] - Since hpmcounter10 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[10] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[10] ? UNDEFINED_LEGAL : 0; - HPM11: - location: 11 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[11] == true"] - When set, `hpmcounter11.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[11] == false"] - Since hpmcounter11 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[11] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[11] ? UNDEFINED_LEGAL : 0; - HPM12: - location: 12 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[12] == true"] - When set, `hpmcounter12.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[12] == false"] - Since hpmcounter12 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[12] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[12] ? UNDEFINED_LEGAL : 0; - HPM13: - location: 13 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[13] == true"] - When set, `hpmcounter13.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[13] == false"] - Since hpmcounter13 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[13] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[13] ? UNDEFINED_LEGAL : 0; - HPM14: - location: 14 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[14] == true"] - When set, `hpmcounter14.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[14] == false"] - Since hpmcounter14 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[14] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[14] ? UNDEFINED_LEGAL : 0; - HPM15: - location: 15 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[15] == true"] - When set, `hpmcounter15.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[15] == false"] - Since hpmcounter15 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[15] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[15] ? UNDEFINED_LEGAL : 0; - HPM16: - location: 16 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[16] == true"] - When set, `hpmcounter16.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[16] == false"] - Since hpmcounter16 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[16] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[16] ? UNDEFINED_LEGAL : 0; - HPM17: - location: 17 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[17] == true"] - When set, `hpmcounter17.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[17] == false"] - Since hpmcounter17 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[17] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[17] ? UNDEFINED_LEGAL : 0; - HPM18: - location: 18 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[18] == true"] - When set, `hpmcounter18.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[18] == false"] - Since hpmcounter18 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[18] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[18] ? UNDEFINED_LEGAL : 0; - HPM19: - location: 19 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[19] == true"] - When set, `hpmcounter19.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[19] == false"] - Since hpmcounter19 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[19] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[19] ? UNDEFINED_LEGAL : 0; - HPM20: - location: 20 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[20] == true"] - When set, `hpmcounter20.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[20] == false"] - Since hpmcounter20 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[20] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[20] ? UNDEFINED_LEGAL : 0; - HPM21: - location: 21 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[21] == true"] - When set, `hpmcounter21.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[21] == false"] - Since hpmcounter21 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[21] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[21] ? UNDEFINED_LEGAL : 0; - HPM22: - location: 22 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[22] == true"] - When set, `hpmcounter22.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[22] == false"] - Since hpmcounter22 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[22] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[22] ? UNDEFINED_LEGAL : 0; - HPM23: - location: 23 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[23] == true"] - When set, `hpmcounter23.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[23] == false"] - Since hpmcounter23 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[23] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[23] ? UNDEFINED_LEGAL : 0; - HPM24: - location: 24 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[24] == true"] - When set, `hpmcounter24.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[24] == false"] - Since hpmcounter24 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[24] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[24] ? UNDEFINED_LEGAL : 0; - HPM25: - location: 25 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[25] == true"] - When set, `hpmcounter25.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[25] == false"] - Since hpmcounter25 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[25] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[25] ? UNDEFINED_LEGAL : 0; - HPM26: - location: 26 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[26] == true"] - When set, `hpmcounter26.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[26] == false"] - Since hpmcounter26 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[26] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[26] ? UNDEFINED_LEGAL : 0; - HPM27: - location: 27 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[27] == true"] - When set, `hpmcounter27.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[27] == false"] - Since hpmcounter27 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[27] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[27] ? UNDEFINED_LEGAL : 0; - HPM28: - location: 28 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[28] == true"] - When set, `hpmcounter28.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[28] == false"] - Since hpmcounter28 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[28] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[28] ? UNDEFINED_LEGAL : 0; - HPM29: - location: 29 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[29] == true"] - When set, `hpmcounter29.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[29] == false"] - Since hpmcounter29 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[29] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[29] ? UNDEFINED_LEGAL : 0; - HPM30: - location: 30 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[30] == true"] - When set, `hpmcounter30.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[30] == false"] - Since hpmcounter30 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[30] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[30] ? UNDEFINED_LEGAL : 0; - HPM31: - location: 31 - definedBy: Smhpm - description: | - [when="COUNTINHIBIT_EN[31] == true"] - When set, `hpmcounter31.COUNT` stops counting in all privilege modes. - - [when="COUNTINHIBIT_EN[31] == false"] - Since hpmcounter31 is not implemented, this field is read-only zero. - type(): | - return COUNTINHIBIT_EN[31] ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return COUNTINHIBIT_EN[31] ? UNDEFINED_LEGAL : 0; +$schema: csr_schema.json# +kind: csr +name: mcountinhibit +long_name: Machine Counter Inhibit +address: 0x320 +priv_mode: M +length: 32 +description: | + Bits to inhibit (stops counting) performance counters. + + The counter-inhibit register `mcountinhibit` is a *WARL* register that + controls which of the hardware performance-monitoring counters + increment. The settings in this register only control whether the + counters increment; their accessibility is not affected by the setting + of this register. + + When the CY, IR, or HPM__n__ bit in the `mcountinhibit` register is clear, + the `mcycle`, `minstret`, or `mhpmcountern` register increments as usual. + When the CY, IR, or HPM_n_ bit is set, the corresponding counter does + not increment. + + The `mcycle` CSR may be shared between harts on the same core, in which + case the `mcountinhibit.CY` field is also shared between those harts, + and so writes to `mcountinhibit.CY` will be visible to those harts. + + If the `mcountinhibit` register is not implemented, the implementation + behaves as though the register were set to zero. + + [NOTE] + ==== + When the `mcycle` and `minstret` counters are not needed, it is desirable + to conditionally inhibit them to reduce energy consumption. Providing a + single CSR to inhibit all counters also allows the counters to be + atomically sampled. + + Because the `mtime` counter can be shared between multiple cores, it + cannot be inhibited with the `mcountinhibit` mechanism. + ==== + +definedBy: + anyOf: + - name: Sm + - name: Smhpm +fields: + CY: + location: 0 + definedBy: Sm + description: When set, `mcycle.COUNT` stops counting in all privilege modes. + type(): | + return COUNTINHIBIT_EN[0] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[0] ? UNDEFINED_LEGAL : 0; + IR: + location: 2 + definedBy: Sm + description: When set, `minstret.COUNT` stops counting in all privilege modes. + type(): | + return COUNTINHIBIT_EN[2] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[2] ? UNDEFINED_LEGAL : 0; + HPM3: + location: 3 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[3] == true"] + When set, `hpmcounter3.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[3] == false"] + Since hpmcounter3 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[3] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[3] ? UNDEFINED_LEGAL : 0; + HPM4: + location: 4 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[4] == true"] + When set, `hpmcounter4.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[4] == false"] + Since hpmcounter4 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[4] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[4] ? UNDEFINED_LEGAL : 0; + HPM5: + location: 5 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[5] == true"] + When set, `hpmcounter5.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[5] == false"] + Since hpmcounter5 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[5] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[5] ? UNDEFINED_LEGAL : 0; + HPM6: + location: 6 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[6] == true"] + When set, `hpmcounter6.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[6] == false"] + Since hpmcounter6 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[6] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[6] ? UNDEFINED_LEGAL : 0; + HPM7: + location: 7 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[7] == true"] + When set, `hpmcounter7.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[7] == false"] + Since hpmcounter7 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[7] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[7] ? UNDEFINED_LEGAL : 0; + HPM8: + location: 8 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[8] == true"] + When set, `hpmcounter8.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[8] == false"] + Since hpmcounter8 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[8] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[8] ? UNDEFINED_LEGAL : 0; + HPM9: + location: 9 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[9] == true"] + When set, `hpmcounter9.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[9] == false"] + Since hpmcounter9 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[9] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[9] ? UNDEFINED_LEGAL : 0; + HPM10: + location: 10 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[10] == true"] + When set, `hpmcounter10.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[10] == false"] + Since hpmcounter10 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[10] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[10] ? UNDEFINED_LEGAL : 0; + HPM11: + location: 11 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[11] == true"] + When set, `hpmcounter11.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[11] == false"] + Since hpmcounter11 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[11] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[11] ? UNDEFINED_LEGAL : 0; + HPM12: + location: 12 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[12] == true"] + When set, `hpmcounter12.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[12] == false"] + Since hpmcounter12 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[12] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[12] ? UNDEFINED_LEGAL : 0; + HPM13: + location: 13 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[13] == true"] + When set, `hpmcounter13.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[13] == false"] + Since hpmcounter13 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[13] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[13] ? UNDEFINED_LEGAL : 0; + HPM14: + location: 14 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[14] == true"] + When set, `hpmcounter14.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[14] == false"] + Since hpmcounter14 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[14] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[14] ? UNDEFINED_LEGAL : 0; + HPM15: + location: 15 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[15] == true"] + When set, `hpmcounter15.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[15] == false"] + Since hpmcounter15 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[15] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[15] ? UNDEFINED_LEGAL : 0; + HPM16: + location: 16 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[16] == true"] + When set, `hpmcounter16.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[16] == false"] + Since hpmcounter16 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[16] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[16] ? UNDEFINED_LEGAL : 0; + HPM17: + location: 17 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[17] == true"] + When set, `hpmcounter17.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[17] == false"] + Since hpmcounter17 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[17] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[17] ? UNDEFINED_LEGAL : 0; + HPM18: + location: 18 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[18] == true"] + When set, `hpmcounter18.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[18] == false"] + Since hpmcounter18 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[18] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[18] ? UNDEFINED_LEGAL : 0; + HPM19: + location: 19 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[19] == true"] + When set, `hpmcounter19.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[19] == false"] + Since hpmcounter19 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[19] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[19] ? UNDEFINED_LEGAL : 0; + HPM20: + location: 20 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[20] == true"] + When set, `hpmcounter20.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[20] == false"] + Since hpmcounter20 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[20] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[20] ? UNDEFINED_LEGAL : 0; + HPM21: + location: 21 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[21] == true"] + When set, `hpmcounter21.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[21] == false"] + Since hpmcounter21 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[21] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[21] ? UNDEFINED_LEGAL : 0; + HPM22: + location: 22 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[22] == true"] + When set, `hpmcounter22.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[22] == false"] + Since hpmcounter22 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[22] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[22] ? UNDEFINED_LEGAL : 0; + HPM23: + location: 23 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[23] == true"] + When set, `hpmcounter23.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[23] == false"] + Since hpmcounter23 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[23] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[23] ? UNDEFINED_LEGAL : 0; + HPM24: + location: 24 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[24] == true"] + When set, `hpmcounter24.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[24] == false"] + Since hpmcounter24 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[24] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[24] ? UNDEFINED_LEGAL : 0; + HPM25: + location: 25 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[25] == true"] + When set, `hpmcounter25.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[25] == false"] + Since hpmcounter25 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[25] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[25] ? UNDEFINED_LEGAL : 0; + HPM26: + location: 26 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[26] == true"] + When set, `hpmcounter26.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[26] == false"] + Since hpmcounter26 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[26] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[26] ? UNDEFINED_LEGAL : 0; + HPM27: + location: 27 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[27] == true"] + When set, `hpmcounter27.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[27] == false"] + Since hpmcounter27 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[27] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[27] ? UNDEFINED_LEGAL : 0; + HPM28: + location: 28 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[28] == true"] + When set, `hpmcounter28.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[28] == false"] + Since hpmcounter28 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[28] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[28] ? UNDEFINED_LEGAL : 0; + HPM29: + location: 29 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[29] == true"] + When set, `hpmcounter29.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[29] == false"] + Since hpmcounter29 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[29] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[29] ? UNDEFINED_LEGAL : 0; + HPM30: + location: 30 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[30] == true"] + When set, `hpmcounter30.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[30] == false"] + Since hpmcounter30 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[30] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[30] ? UNDEFINED_LEGAL : 0; + HPM31: + location: 31 + definedBy: Smhpm + description: | + [when="COUNTINHIBIT_EN[31] == true"] + When set, `hpmcounter31.COUNT` stops counting in all privilege modes. + + [when="COUNTINHIBIT_EN[31] == false"] + Since hpmcounter31 is not implemented, this field is read-only zero. + type(): | + return COUNTINHIBIT_EN[31] ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return COUNTINHIBIT_EN[31] ? UNDEFINED_LEGAL : 0; diff --git a/arch/csr/Zihpm/hpmcounter10.yaml b/arch/csr/Zihpm/hpmcounter10.yaml index ce104a53c..f88d8c047 100644 --- a/arch/csr/Zihpm/hpmcounter10.yaml +++ b/arch/csr/Zihpm/hpmcounter10.yaml @@ -4,100 +4,102 @@ -hpmcounter10: - long_name: User-mode Hardware Performance Counter 7 - address: 0xC0A - description: | - Alias for M-mode CSR `mhpmcounter10`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter10 +long_name: User-mode Hardware Performance Counter 7 +address: 0xC0A +description: | + Alias for M-mode CSR `mhpmcounter10`. - Privilege mode access is controlled with `mcounteren.HPM10` - <%- if ext?(:S) -%> - , `scounteren.HPM10` - <%- if ext?(:H) -%> - , and `hcounteren.HPM10` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM10` + <%- if ext?(:S) -%> + , `scounteren.HPM10` + <%- if ext?(:H) -%> + , and `hcounteren.HPM10` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM10`# .2+h! [.rotate]#`scounteren.HPM10`# .2+h! [.rotate]#`hcounteren.HPM10`# - 4+^.>h! `hpmcounter10` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM10`# .2+h! [.rotate]#`scounteren.HPM10`# .2+h! [.rotate]#`hcounteren.HPM10`# + 4+^.>h! `hpmcounter10` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM10`# .2+h! [.rotate]#`scounteren.HPM10`# - 2+^.>h! `hpmcounter10` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM10`# .2+h! [.rotate]#`scounteren.HPM10`# + 2+^.>h! `hpmcounter10` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM10`# - ^.>h! `hpmcounter10` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM10`# + ^.>h! `hpmcounter10` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter10.COUNT - description: Alias of `mhpmcounter10.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter10.COUNT + description: Alias of `mhpmcounter10.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM10 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM10 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM10 & CSR[scounteren].HPM10) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM10 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM10 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM10 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM10 & CSR[scounteren].HPM10) == 1'b0) && (CSR[mcounteren].HPM10 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM10 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM10 & CSR[scounteren].HPM10) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM10 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM10 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM10 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM10 & CSR[scounteren].HPM10) == 1'b0) && (CSR[mcounteren].HPM10 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM10 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(10); + return read_hpm_counter(10); diff --git a/arch/csr/Zihpm/hpmcounter10h.yaml b/arch/csr/Zihpm/hpmcounter10h.yaml index 0b72fa1e5..4f524ae5a 100644 --- a/arch/csr/Zihpm/hpmcounter10h.yaml +++ b/arch/csr/Zihpm/hpmcounter10h.yaml @@ -4,70 +4,72 @@ -hpmcounter10h: - long_name: User-mode Hardware Performance Counter 7, high half - address: 0xC8A - description: | - Alias for M-mode CSR `mhpmcounter10h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter10h +long_name: User-mode Hardware Performance Counter 7, high half +address: 0xC8A +description: | + Alias for M-mode CSR `mhpmcounter10h`. - Privilege mode access is controlled with `mcounteren.HPM10`, `scounteren.HPM10`, and `hcounteren.HPM10` as follows: + Privilege mode access is controlled with `mcounteren.HPM10`, `scounteren.HPM10`, and `hcounteren.HPM10` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM10`# .2+h! [.rotate]#`scounteren.HPM10`# .2+h! [.rotate]#`hcounteren.HPM10`# - 4+^.>h! `hpmcounter10h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM10`# .2+h! [.rotate]#`scounteren.HPM10`# .2+h! [.rotate]#`hcounteren.HPM10`# + 4+^.>h! `hpmcounter10h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter10h.COUNT - description: Alias of `mhpmcounter10h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter10h.COUNT + description: Alias of `mhpmcounter10h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM10 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM10 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM10 & CSR[scounteren].HPM10) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM10 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM10 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM10 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM10 & CSR[scounteren].HPM10) == 1'b0) && (CSR[mcounteren].HPM10 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM10 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM10 & CSR[scounteren].HPM10) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM10 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM10 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM10 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM10 & CSR[scounteren].HPM10) == 1'b0) && (CSR[mcounteren].HPM10 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM10 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(10)[63:32]; + return read_hpm_counter(10)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter11.yaml b/arch/csr/Zihpm/hpmcounter11.yaml index 719474378..f0b6df2c0 100644 --- a/arch/csr/Zihpm/hpmcounter11.yaml +++ b/arch/csr/Zihpm/hpmcounter11.yaml @@ -4,100 +4,102 @@ -hpmcounter11: - long_name: User-mode Hardware Performance Counter 8 - address: 0xC0B - description: | - Alias for M-mode CSR `mhpmcounter11`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter11 +long_name: User-mode Hardware Performance Counter 8 +address: 0xC0B +description: | + Alias for M-mode CSR `mhpmcounter11`. - Privilege mode access is controlled with `mcounteren.HPM11` - <%- if ext?(:S) -%> - , `scounteren.HPM11` - <%- if ext?(:H) -%> - , and `hcounteren.HPM11` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM11` + <%- if ext?(:S) -%> + , `scounteren.HPM11` + <%- if ext?(:H) -%> + , and `hcounteren.HPM11` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM11`# .2+h! [.rotate]#`scounteren.HPM11`# .2+h! [.rotate]#`hcounteren.HPM11`# - 4+^.>h! `hpmcounter11` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM11`# .2+h! [.rotate]#`scounteren.HPM11`# .2+h! [.rotate]#`hcounteren.HPM11`# + 4+^.>h! `hpmcounter11` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM11`# .2+h! [.rotate]#`scounteren.HPM11`# - 2+^.>h! `hpmcounter11` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM11`# .2+h! [.rotate]#`scounteren.HPM11`# + 2+^.>h! `hpmcounter11` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM11`# - ^.>h! `hpmcounter11` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM11`# + ^.>h! `hpmcounter11` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter11.COUNT - description: Alias of `mhpmcounter11.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter11.COUNT + description: Alias of `mhpmcounter11.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM11 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM11 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM11 & CSR[scounteren].HPM11) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM11 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM11 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM11 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM11 & CSR[scounteren].HPM11) == 1'b0) && (CSR[mcounteren].HPM11 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM11 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM11 & CSR[scounteren].HPM11) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM11 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM11 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM11 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM11 & CSR[scounteren].HPM11) == 1'b0) && (CSR[mcounteren].HPM11 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM11 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(11); + return read_hpm_counter(11); diff --git a/arch/csr/Zihpm/hpmcounter11h.yaml b/arch/csr/Zihpm/hpmcounter11h.yaml index 3992b01bb..ae1d606a7 100644 --- a/arch/csr/Zihpm/hpmcounter11h.yaml +++ b/arch/csr/Zihpm/hpmcounter11h.yaml @@ -4,70 +4,72 @@ -hpmcounter11h: - long_name: User-mode Hardware Performance Counter 8, high half - address: 0xC8B - description: | - Alias for M-mode CSR `mhpmcounter11h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter11h +long_name: User-mode Hardware Performance Counter 8, high half +address: 0xC8B +description: | + Alias for M-mode CSR `mhpmcounter11h`. - Privilege mode access is controlled with `mcounteren.HPM11`, `scounteren.HPM11`, and `hcounteren.HPM11` as follows: + Privilege mode access is controlled with `mcounteren.HPM11`, `scounteren.HPM11`, and `hcounteren.HPM11` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM11`# .2+h! [.rotate]#`scounteren.HPM11`# .2+h! [.rotate]#`hcounteren.HPM11`# - 4+^.>h! `hpmcounter11h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM11`# .2+h! [.rotate]#`scounteren.HPM11`# .2+h! [.rotate]#`hcounteren.HPM11`# + 4+^.>h! `hpmcounter11h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter11h.COUNT - description: Alias of `mhpmcounter11h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter11h.COUNT + description: Alias of `mhpmcounter11h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM11 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM11 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM11 & CSR[scounteren].HPM11) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM11 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM11 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM11 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM11 & CSR[scounteren].HPM11) == 1'b0) && (CSR[mcounteren].HPM11 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM11 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM11 & CSR[scounteren].HPM11) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM11 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM11 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM11 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM11 & CSR[scounteren].HPM11) == 1'b0) && (CSR[mcounteren].HPM11 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM11 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(11)[63:32]; + return read_hpm_counter(11)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter12.yaml b/arch/csr/Zihpm/hpmcounter12.yaml index b08bb753b..ac643a168 100644 --- a/arch/csr/Zihpm/hpmcounter12.yaml +++ b/arch/csr/Zihpm/hpmcounter12.yaml @@ -4,100 +4,102 @@ -hpmcounter12: - long_name: User-mode Hardware Performance Counter 9 - address: 0xC0C - description: | - Alias for M-mode CSR `mhpmcounter12`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter12 +long_name: User-mode Hardware Performance Counter 9 +address: 0xC0C +description: | + Alias for M-mode CSR `mhpmcounter12`. - Privilege mode access is controlled with `mcounteren.HPM12` - <%- if ext?(:S) -%> - , `scounteren.HPM12` - <%- if ext?(:H) -%> - , and `hcounteren.HPM12` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM12` + <%- if ext?(:S) -%> + , `scounteren.HPM12` + <%- if ext?(:H) -%> + , and `hcounteren.HPM12` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM12`# .2+h! [.rotate]#`scounteren.HPM12`# .2+h! [.rotate]#`hcounteren.HPM12`# - 4+^.>h! `hpmcounter12` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM12`# .2+h! [.rotate]#`scounteren.HPM12`# .2+h! [.rotate]#`hcounteren.HPM12`# + 4+^.>h! `hpmcounter12` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM12`# .2+h! [.rotate]#`scounteren.HPM12`# - 2+^.>h! `hpmcounter12` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM12`# .2+h! [.rotate]#`scounteren.HPM12`# + 2+^.>h! `hpmcounter12` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM12`# - ^.>h! `hpmcounter12` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM12`# + ^.>h! `hpmcounter12` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter12.COUNT - description: Alias of `mhpmcounter12.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter12.COUNT + description: Alias of `mhpmcounter12.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM12 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM12 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM12 & CSR[scounteren].HPM12) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM12 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM12 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM12 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM12 & CSR[scounteren].HPM12) == 1'b0) && (CSR[mcounteren].HPM12 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM12 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM12 & CSR[scounteren].HPM12) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM12 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM12 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM12 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM12 & CSR[scounteren].HPM12) == 1'b0) && (CSR[mcounteren].HPM12 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM12 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(12); + return read_hpm_counter(12); diff --git a/arch/csr/Zihpm/hpmcounter12h.yaml b/arch/csr/Zihpm/hpmcounter12h.yaml index ca5ee7136..3f4cda485 100644 --- a/arch/csr/Zihpm/hpmcounter12h.yaml +++ b/arch/csr/Zihpm/hpmcounter12h.yaml @@ -4,70 +4,72 @@ -hpmcounter12h: - long_name: User-mode Hardware Performance Counter 9, high half - address: 0xC8C - description: | - Alias for M-mode CSR `mhpmcounter12h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter12h +long_name: User-mode Hardware Performance Counter 9, high half +address: 0xC8C +description: | + Alias for M-mode CSR `mhpmcounter12h`. - Privilege mode access is controlled with `mcounteren.HPM12`, `scounteren.HPM12`, and `hcounteren.HPM12` as follows: + Privilege mode access is controlled with `mcounteren.HPM12`, `scounteren.HPM12`, and `hcounteren.HPM12` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM12`# .2+h! [.rotate]#`scounteren.HPM12`# .2+h! [.rotate]#`hcounteren.HPM12`# - 4+^.>h! `hpmcounter12h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM12`# .2+h! [.rotate]#`scounteren.HPM12`# .2+h! [.rotate]#`hcounteren.HPM12`# + 4+^.>h! `hpmcounter12h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter12h.COUNT - description: Alias of `mhpmcounter12h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter12h.COUNT + description: Alias of `mhpmcounter12h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM12 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM12 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM12 & CSR[scounteren].HPM12) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM12 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM12 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM12 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM12 & CSR[scounteren].HPM12) == 1'b0) && (CSR[mcounteren].HPM12 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM12 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM12 & CSR[scounteren].HPM12) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM12 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM12 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM12 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM12 & CSR[scounteren].HPM12) == 1'b0) && (CSR[mcounteren].HPM12 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM12 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(12)[63:32]; + return read_hpm_counter(12)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter13.yaml b/arch/csr/Zihpm/hpmcounter13.yaml index 8a6f76f14..68a8c0e12 100644 --- a/arch/csr/Zihpm/hpmcounter13.yaml +++ b/arch/csr/Zihpm/hpmcounter13.yaml @@ -4,100 +4,102 @@ -hpmcounter13: - long_name: User-mode Hardware Performance Counter 10 - address: 0xC0D - description: | - Alias for M-mode CSR `mhpmcounter13`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter13 +long_name: User-mode Hardware Performance Counter 10 +address: 0xC0D +description: | + Alias for M-mode CSR `mhpmcounter13`. - Privilege mode access is controlled with `mcounteren.HPM13` - <%- if ext?(:S) -%> - , `scounteren.HPM13` - <%- if ext?(:H) -%> - , and `hcounteren.HPM13` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM13` + <%- if ext?(:S) -%> + , `scounteren.HPM13` + <%- if ext?(:H) -%> + , and `hcounteren.HPM13` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM13`# .2+h! [.rotate]#`scounteren.HPM13`# .2+h! [.rotate]#`hcounteren.HPM13`# - 4+^.>h! `hpmcounter13` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM13`# .2+h! [.rotate]#`scounteren.HPM13`# .2+h! [.rotate]#`hcounteren.HPM13`# + 4+^.>h! `hpmcounter13` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM13`# .2+h! [.rotate]#`scounteren.HPM13`# - 2+^.>h! `hpmcounter13` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM13`# .2+h! [.rotate]#`scounteren.HPM13`# + 2+^.>h! `hpmcounter13` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM13`# - ^.>h! `hpmcounter13` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM13`# + ^.>h! `hpmcounter13` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter13.COUNT - description: Alias of `mhpmcounter13.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter13.COUNT + description: Alias of `mhpmcounter13.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM13 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM13 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM13 & CSR[scounteren].HPM13) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM13 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM13 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM13 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM13 & CSR[scounteren].HPM13) == 1'b0) && (CSR[mcounteren].HPM13 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM13 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM13 & CSR[scounteren].HPM13) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM13 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM13 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM13 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM13 & CSR[scounteren].HPM13) == 1'b0) && (CSR[mcounteren].HPM13 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM13 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(13); + return read_hpm_counter(13); diff --git a/arch/csr/Zihpm/hpmcounter13h.yaml b/arch/csr/Zihpm/hpmcounter13h.yaml index cb821c29f..938204ac0 100644 --- a/arch/csr/Zihpm/hpmcounter13h.yaml +++ b/arch/csr/Zihpm/hpmcounter13h.yaml @@ -4,70 +4,72 @@ -hpmcounter13h: - long_name: User-mode Hardware Performance Counter 10, high half - address: 0xC8D - description: | - Alias for M-mode CSR `mhpmcounter13h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter13h +long_name: User-mode Hardware Performance Counter 10, high half +address: 0xC8D +description: | + Alias for M-mode CSR `mhpmcounter13h`. - Privilege mode access is controlled with `mcounteren.HPM13`, `scounteren.HPM13`, and `hcounteren.HPM13` as follows: + Privilege mode access is controlled with `mcounteren.HPM13`, `scounteren.HPM13`, and `hcounteren.HPM13` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM13`# .2+h! [.rotate]#`scounteren.HPM13`# .2+h! [.rotate]#`hcounteren.HPM13`# - 4+^.>h! `hpmcounter13h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM13`# .2+h! [.rotate]#`scounteren.HPM13`# .2+h! [.rotate]#`hcounteren.HPM13`# + 4+^.>h! `hpmcounter13h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter13h.COUNT - description: Alias of `mhpmcounter13h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter13h.COUNT + description: Alias of `mhpmcounter13h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM13 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM13 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM13 & CSR[scounteren].HPM13) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM13 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM13 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM13 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM13 & CSR[scounteren].HPM13) == 1'b0) && (CSR[mcounteren].HPM13 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM13 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM13 & CSR[scounteren].HPM13) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM13 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM13 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM13 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM13 & CSR[scounteren].HPM13) == 1'b0) && (CSR[mcounteren].HPM13 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM13 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(13)[63:32]; + return read_hpm_counter(13)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter14.yaml b/arch/csr/Zihpm/hpmcounter14.yaml index d458fcd1e..c547b8d74 100644 --- a/arch/csr/Zihpm/hpmcounter14.yaml +++ b/arch/csr/Zihpm/hpmcounter14.yaml @@ -4,100 +4,102 @@ -hpmcounter14: - long_name: User-mode Hardware Performance Counter 11 - address: 0xC0E - description: | - Alias for M-mode CSR `mhpmcounter14`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter14 +long_name: User-mode Hardware Performance Counter 11 +address: 0xC0E +description: | + Alias for M-mode CSR `mhpmcounter14`. - Privilege mode access is controlled with `mcounteren.HPM14` - <%- if ext?(:S) -%> - , `scounteren.HPM14` - <%- if ext?(:H) -%> - , and `hcounteren.HPM14` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM14` + <%- if ext?(:S) -%> + , `scounteren.HPM14` + <%- if ext?(:H) -%> + , and `hcounteren.HPM14` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM14`# .2+h! [.rotate]#`scounteren.HPM14`# .2+h! [.rotate]#`hcounteren.HPM14`# - 4+^.>h! `hpmcounter14` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM14`# .2+h! [.rotate]#`scounteren.HPM14`# .2+h! [.rotate]#`hcounteren.HPM14`# + 4+^.>h! `hpmcounter14` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM14`# .2+h! [.rotate]#`scounteren.HPM14`# - 2+^.>h! `hpmcounter14` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM14`# .2+h! [.rotate]#`scounteren.HPM14`# + 2+^.>h! `hpmcounter14` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM14`# - ^.>h! `hpmcounter14` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM14`# + ^.>h! `hpmcounter14` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter14.COUNT - description: Alias of `mhpmcounter14.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter14.COUNT + description: Alias of `mhpmcounter14.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM14 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM14 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM14 & CSR[scounteren].HPM14) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM14 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM14 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM14 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM14 & CSR[scounteren].HPM14) == 1'b0) && (CSR[mcounteren].HPM14 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM14 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM14 & CSR[scounteren].HPM14) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM14 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM14 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM14 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM14 & CSR[scounteren].HPM14) == 1'b0) && (CSR[mcounteren].HPM14 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM14 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(14); + return read_hpm_counter(14); diff --git a/arch/csr/Zihpm/hpmcounter14h.yaml b/arch/csr/Zihpm/hpmcounter14h.yaml index 50ca55033..79877a08f 100644 --- a/arch/csr/Zihpm/hpmcounter14h.yaml +++ b/arch/csr/Zihpm/hpmcounter14h.yaml @@ -4,70 +4,72 @@ -hpmcounter14h: - long_name: User-mode Hardware Performance Counter 11, high half - address: 0xC8E - description: | - Alias for M-mode CSR `mhpmcounter14h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter14h +long_name: User-mode Hardware Performance Counter 11, high half +address: 0xC8E +description: | + Alias for M-mode CSR `mhpmcounter14h`. - Privilege mode access is controlled with `mcounteren.HPM14`, `scounteren.HPM14`, and `hcounteren.HPM14` as follows: + Privilege mode access is controlled with `mcounteren.HPM14`, `scounteren.HPM14`, and `hcounteren.HPM14` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM14`# .2+h! [.rotate]#`scounteren.HPM14`# .2+h! [.rotate]#`hcounteren.HPM14`# - 4+^.>h! `hpmcounter14h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM14`# .2+h! [.rotate]#`scounteren.HPM14`# .2+h! [.rotate]#`hcounteren.HPM14`# + 4+^.>h! `hpmcounter14h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter14h.COUNT - description: Alias of `mhpmcounter14h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter14h.COUNT + description: Alias of `mhpmcounter14h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM14 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM14 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM14 & CSR[scounteren].HPM14) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM14 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM14 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM14 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM14 & CSR[scounteren].HPM14) == 1'b0) && (CSR[mcounteren].HPM14 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM14 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM14 & CSR[scounteren].HPM14) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM14 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM14 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM14 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM14 & CSR[scounteren].HPM14) == 1'b0) && (CSR[mcounteren].HPM14 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM14 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(14)[63:32]; + return read_hpm_counter(14)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter15.yaml b/arch/csr/Zihpm/hpmcounter15.yaml index f5a39336b..418b7c3cd 100644 --- a/arch/csr/Zihpm/hpmcounter15.yaml +++ b/arch/csr/Zihpm/hpmcounter15.yaml @@ -4,100 +4,102 @@ -hpmcounter15: - long_name: User-mode Hardware Performance Counter 12 - address: 0xC0F - description: | - Alias for M-mode CSR `mhpmcounter15`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter15 +long_name: User-mode Hardware Performance Counter 12 +address: 0xC0F +description: | + Alias for M-mode CSR `mhpmcounter15`. - Privilege mode access is controlled with `mcounteren.HPM15` - <%- if ext?(:S) -%> - , `scounteren.HPM15` - <%- if ext?(:H) -%> - , and `hcounteren.HPM15` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM15` + <%- if ext?(:S) -%> + , `scounteren.HPM15` + <%- if ext?(:H) -%> + , and `hcounteren.HPM15` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM15`# .2+h! [.rotate]#`scounteren.HPM15`# .2+h! [.rotate]#`hcounteren.HPM15`# - 4+^.>h! `hpmcounter15` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM15`# .2+h! [.rotate]#`scounteren.HPM15`# .2+h! [.rotate]#`hcounteren.HPM15`# + 4+^.>h! `hpmcounter15` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM15`# .2+h! [.rotate]#`scounteren.HPM15`# - 2+^.>h! `hpmcounter15` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM15`# .2+h! [.rotate]#`scounteren.HPM15`# + 2+^.>h! `hpmcounter15` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM15`# - ^.>h! `hpmcounter15` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM15`# + ^.>h! `hpmcounter15` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter15.COUNT - description: Alias of `mhpmcounter15.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter15.COUNT + description: Alias of `mhpmcounter15.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM15 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM15 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM15 & CSR[scounteren].HPM15) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM15 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM15 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM15 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM15 & CSR[scounteren].HPM15) == 1'b0) && (CSR[mcounteren].HPM15 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM15 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM15 & CSR[scounteren].HPM15) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM15 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM15 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM15 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM15 & CSR[scounteren].HPM15) == 1'b0) && (CSR[mcounteren].HPM15 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM15 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(15); + return read_hpm_counter(15); diff --git a/arch/csr/Zihpm/hpmcounter15h.yaml b/arch/csr/Zihpm/hpmcounter15h.yaml index 04b4b681b..bba8da3d1 100644 --- a/arch/csr/Zihpm/hpmcounter15h.yaml +++ b/arch/csr/Zihpm/hpmcounter15h.yaml @@ -4,70 +4,72 @@ -hpmcounter15h: - long_name: User-mode Hardware Performance Counter 12, high half - address: 0xC8F - description: | - Alias for M-mode CSR `mhpmcounter15h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter15h +long_name: User-mode Hardware Performance Counter 12, high half +address: 0xC8F +description: | + Alias for M-mode CSR `mhpmcounter15h`. - Privilege mode access is controlled with `mcounteren.HPM15`, `scounteren.HPM15`, and `hcounteren.HPM15` as follows: + Privilege mode access is controlled with `mcounteren.HPM15`, `scounteren.HPM15`, and `hcounteren.HPM15` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM15`# .2+h! [.rotate]#`scounteren.HPM15`# .2+h! [.rotate]#`hcounteren.HPM15`# - 4+^.>h! `hpmcounter15h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM15`# .2+h! [.rotate]#`scounteren.HPM15`# .2+h! [.rotate]#`hcounteren.HPM15`# + 4+^.>h! `hpmcounter15h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter15h.COUNT - description: Alias of `mhpmcounter15h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter15h.COUNT + description: Alias of `mhpmcounter15h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM15 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM15 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM15 & CSR[scounteren].HPM15) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM15 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM15 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM15 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM15 & CSR[scounteren].HPM15) == 1'b0) && (CSR[mcounteren].HPM15 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM15 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM15 & CSR[scounteren].HPM15) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM15 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM15 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM15 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM15 & CSR[scounteren].HPM15) == 1'b0) && (CSR[mcounteren].HPM15 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM15 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(15)[63:32]; + return read_hpm_counter(15)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter16.yaml b/arch/csr/Zihpm/hpmcounter16.yaml index 5e3bdfaf5..4c46e4ab6 100644 --- a/arch/csr/Zihpm/hpmcounter16.yaml +++ b/arch/csr/Zihpm/hpmcounter16.yaml @@ -4,100 +4,102 @@ -hpmcounter16: - long_name: User-mode Hardware Performance Counter 13 - address: 0xC10 - description: | - Alias for M-mode CSR `mhpmcounter16`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter16 +long_name: User-mode Hardware Performance Counter 13 +address: 0xC10 +description: | + Alias for M-mode CSR `mhpmcounter16`. - Privilege mode access is controlled with `mcounteren.HPM16` - <%- if ext?(:S) -%> - , `scounteren.HPM16` - <%- if ext?(:H) -%> - , and `hcounteren.HPM16` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM16` + <%- if ext?(:S) -%> + , `scounteren.HPM16` + <%- if ext?(:H) -%> + , and `hcounteren.HPM16` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM16`# .2+h! [.rotate]#`scounteren.HPM16`# .2+h! [.rotate]#`hcounteren.HPM16`# - 4+^.>h! `hpmcounter16` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM16`# .2+h! [.rotate]#`scounteren.HPM16`# .2+h! [.rotate]#`hcounteren.HPM16`# + 4+^.>h! `hpmcounter16` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM16`# .2+h! [.rotate]#`scounteren.HPM16`# - 2+^.>h! `hpmcounter16` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM16`# .2+h! [.rotate]#`scounteren.HPM16`# + 2+^.>h! `hpmcounter16` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM16`# - ^.>h! `hpmcounter16` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM16`# + ^.>h! `hpmcounter16` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter16.COUNT - description: Alias of `mhpmcounter16.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter16.COUNT + description: Alias of `mhpmcounter16.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM16 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM16 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM16 & CSR[scounteren].HPM16) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM16 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM16 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM16 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM16 & CSR[scounteren].HPM16) == 1'b0) && (CSR[mcounteren].HPM16 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM16 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM16 & CSR[scounteren].HPM16) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM16 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM16 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM16 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM16 & CSR[scounteren].HPM16) == 1'b0) && (CSR[mcounteren].HPM16 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM16 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(16); + return read_hpm_counter(16); diff --git a/arch/csr/Zihpm/hpmcounter16h.yaml b/arch/csr/Zihpm/hpmcounter16h.yaml index e0743e4fe..5e7db6fe5 100644 --- a/arch/csr/Zihpm/hpmcounter16h.yaml +++ b/arch/csr/Zihpm/hpmcounter16h.yaml @@ -4,70 +4,72 @@ -hpmcounter16h: - long_name: User-mode Hardware Performance Counter 13, high half - address: 0xC90 - description: | - Alias for M-mode CSR `mhpmcounter16h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter16h +long_name: User-mode Hardware Performance Counter 13, high half +address: 0xC90 +description: | + Alias for M-mode CSR `mhpmcounter16h`. - Privilege mode access is controlled with `mcounteren.HPM16`, `scounteren.HPM16`, and `hcounteren.HPM16` as follows: + Privilege mode access is controlled with `mcounteren.HPM16`, `scounteren.HPM16`, and `hcounteren.HPM16` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM16`# .2+h! [.rotate]#`scounteren.HPM16`# .2+h! [.rotate]#`hcounteren.HPM16`# - 4+^.>h! `hpmcounter16h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM16`# .2+h! [.rotate]#`scounteren.HPM16`# .2+h! [.rotate]#`hcounteren.HPM16`# + 4+^.>h! `hpmcounter16h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter16h.COUNT - description: Alias of `mhpmcounter16h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter16h.COUNT + description: Alias of `mhpmcounter16h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM16 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM16 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM16 & CSR[scounteren].HPM16) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM16 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM16 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM16 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM16 & CSR[scounteren].HPM16) == 1'b0) && (CSR[mcounteren].HPM16 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM16 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM16 & CSR[scounteren].HPM16) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM16 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM16 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM16 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM16 & CSR[scounteren].HPM16) == 1'b0) && (CSR[mcounteren].HPM16 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM16 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(16)[63:32]; + return read_hpm_counter(16)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter17.yaml b/arch/csr/Zihpm/hpmcounter17.yaml index 3dbff2624..bcc2844fd 100644 --- a/arch/csr/Zihpm/hpmcounter17.yaml +++ b/arch/csr/Zihpm/hpmcounter17.yaml @@ -4,100 +4,102 @@ -hpmcounter17: - long_name: User-mode Hardware Performance Counter 14 - address: 0xC11 - description: | - Alias for M-mode CSR `mhpmcounter17`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter17 +long_name: User-mode Hardware Performance Counter 14 +address: 0xC11 +description: | + Alias for M-mode CSR `mhpmcounter17`. - Privilege mode access is controlled with `mcounteren.HPM17` - <%- if ext?(:S) -%> - , `scounteren.HPM17` - <%- if ext?(:H) -%> - , and `hcounteren.HPM17` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM17` + <%- if ext?(:S) -%> + , `scounteren.HPM17` + <%- if ext?(:H) -%> + , and `hcounteren.HPM17` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM17`# .2+h! [.rotate]#`scounteren.HPM17`# .2+h! [.rotate]#`hcounteren.HPM17`# - 4+^.>h! `hpmcounter17` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM17`# .2+h! [.rotate]#`scounteren.HPM17`# .2+h! [.rotate]#`hcounteren.HPM17`# + 4+^.>h! `hpmcounter17` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM17`# .2+h! [.rotate]#`scounteren.HPM17`# - 2+^.>h! `hpmcounter17` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM17`# .2+h! [.rotate]#`scounteren.HPM17`# + 2+^.>h! `hpmcounter17` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM17`# - ^.>h! `hpmcounter17` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM17`# + ^.>h! `hpmcounter17` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter17.COUNT - description: Alias of `mhpmcounter17.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter17.COUNT + description: Alias of `mhpmcounter17.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM17 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM17 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM17 & CSR[scounteren].HPM17) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM17 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM17 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM17 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM17 & CSR[scounteren].HPM17) == 1'b0) && (CSR[mcounteren].HPM17 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM17 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM17 & CSR[scounteren].HPM17) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM17 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM17 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM17 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM17 & CSR[scounteren].HPM17) == 1'b0) && (CSR[mcounteren].HPM17 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM17 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(17); + return read_hpm_counter(17); diff --git a/arch/csr/Zihpm/hpmcounter17h.yaml b/arch/csr/Zihpm/hpmcounter17h.yaml index a6d994641..de64d2915 100644 --- a/arch/csr/Zihpm/hpmcounter17h.yaml +++ b/arch/csr/Zihpm/hpmcounter17h.yaml @@ -4,70 +4,72 @@ -hpmcounter17h: - long_name: User-mode Hardware Performance Counter 14, high half - address: 0xC91 - description: | - Alias for M-mode CSR `mhpmcounter17h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter17h +long_name: User-mode Hardware Performance Counter 14, high half +address: 0xC91 +description: | + Alias for M-mode CSR `mhpmcounter17h`. - Privilege mode access is controlled with `mcounteren.HPM17`, `scounteren.HPM17`, and `hcounteren.HPM17` as follows: + Privilege mode access is controlled with `mcounteren.HPM17`, `scounteren.HPM17`, and `hcounteren.HPM17` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM17`# .2+h! [.rotate]#`scounteren.HPM17`# .2+h! [.rotate]#`hcounteren.HPM17`# - 4+^.>h! `hpmcounter17h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM17`# .2+h! [.rotate]#`scounteren.HPM17`# .2+h! [.rotate]#`hcounteren.HPM17`# + 4+^.>h! `hpmcounter17h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter17h.COUNT - description: Alias of `mhpmcounter17h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter17h.COUNT + description: Alias of `mhpmcounter17h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM17 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM17 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM17 & CSR[scounteren].HPM17) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM17 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM17 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM17 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM17 & CSR[scounteren].HPM17) == 1'b0) && (CSR[mcounteren].HPM17 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM17 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM17 & CSR[scounteren].HPM17) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM17 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM17 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM17 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM17 & CSR[scounteren].HPM17) == 1'b0) && (CSR[mcounteren].HPM17 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM17 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(17)[63:32]; + return read_hpm_counter(17)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter18.yaml b/arch/csr/Zihpm/hpmcounter18.yaml index 619ac99ff..35219de64 100644 --- a/arch/csr/Zihpm/hpmcounter18.yaml +++ b/arch/csr/Zihpm/hpmcounter18.yaml @@ -4,100 +4,102 @@ -hpmcounter18: - long_name: User-mode Hardware Performance Counter 15 - address: 0xC12 - description: | - Alias for M-mode CSR `mhpmcounter18`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter18 +long_name: User-mode Hardware Performance Counter 15 +address: 0xC12 +description: | + Alias for M-mode CSR `mhpmcounter18`. - Privilege mode access is controlled with `mcounteren.HPM18` - <%- if ext?(:S) -%> - , `scounteren.HPM18` - <%- if ext?(:H) -%> - , and `hcounteren.HPM18` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM18` + <%- if ext?(:S) -%> + , `scounteren.HPM18` + <%- if ext?(:H) -%> + , and `hcounteren.HPM18` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM18`# .2+h! [.rotate]#`scounteren.HPM18`# .2+h! [.rotate]#`hcounteren.HPM18`# - 4+^.>h! `hpmcounter18` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM18`# .2+h! [.rotate]#`scounteren.HPM18`# .2+h! [.rotate]#`hcounteren.HPM18`# + 4+^.>h! `hpmcounter18` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM18`# .2+h! [.rotate]#`scounteren.HPM18`# - 2+^.>h! `hpmcounter18` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM18`# .2+h! [.rotate]#`scounteren.HPM18`# + 2+^.>h! `hpmcounter18` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM18`# - ^.>h! `hpmcounter18` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM18`# + ^.>h! `hpmcounter18` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter18.COUNT - description: Alias of `mhpmcounter18.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter18.COUNT + description: Alias of `mhpmcounter18.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM18 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM18 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM18 & CSR[scounteren].HPM18) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM18 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM18 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM18 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM18 & CSR[scounteren].HPM18) == 1'b0) && (CSR[mcounteren].HPM18 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM18 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM18 & CSR[scounteren].HPM18) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM18 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM18 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM18 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM18 & CSR[scounteren].HPM18) == 1'b0) && (CSR[mcounteren].HPM18 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM18 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(18); + return read_hpm_counter(18); diff --git a/arch/csr/Zihpm/hpmcounter18h.yaml b/arch/csr/Zihpm/hpmcounter18h.yaml index 2d72f8d46..794dddb2b 100644 --- a/arch/csr/Zihpm/hpmcounter18h.yaml +++ b/arch/csr/Zihpm/hpmcounter18h.yaml @@ -4,70 +4,72 @@ -hpmcounter18h: - long_name: User-mode Hardware Performance Counter 15, high half - address: 0xC92 - description: | - Alias for M-mode CSR `mhpmcounter18h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter18h +long_name: User-mode Hardware Performance Counter 15, high half +address: 0xC92 +description: | + Alias for M-mode CSR `mhpmcounter18h`. - Privilege mode access is controlled with `mcounteren.HPM18`, `scounteren.HPM18`, and `hcounteren.HPM18` as follows: + Privilege mode access is controlled with `mcounteren.HPM18`, `scounteren.HPM18`, and `hcounteren.HPM18` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM18`# .2+h! [.rotate]#`scounteren.HPM18`# .2+h! [.rotate]#`hcounteren.HPM18`# - 4+^.>h! `hpmcounter18h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM18`# .2+h! [.rotate]#`scounteren.HPM18`# .2+h! [.rotate]#`hcounteren.HPM18`# + 4+^.>h! `hpmcounter18h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter18h.COUNT - description: Alias of `mhpmcounter18h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter18h.COUNT + description: Alias of `mhpmcounter18h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM18 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM18 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM18 & CSR[scounteren].HPM18) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM18 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM18 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM18 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM18 & CSR[scounteren].HPM18) == 1'b0) && (CSR[mcounteren].HPM18 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM18 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM18 & CSR[scounteren].HPM18) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM18 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM18 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM18 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM18 & CSR[scounteren].HPM18) == 1'b0) && (CSR[mcounteren].HPM18 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM18 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(18)[63:32]; + return read_hpm_counter(18)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter19.yaml b/arch/csr/Zihpm/hpmcounter19.yaml index 65ef79de5..e1e9e8714 100644 --- a/arch/csr/Zihpm/hpmcounter19.yaml +++ b/arch/csr/Zihpm/hpmcounter19.yaml @@ -4,100 +4,102 @@ -hpmcounter19: - long_name: User-mode Hardware Performance Counter 16 - address: 0xC13 - description: | - Alias for M-mode CSR `mhpmcounter19`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter19 +long_name: User-mode Hardware Performance Counter 16 +address: 0xC13 +description: | + Alias for M-mode CSR `mhpmcounter19`. - Privilege mode access is controlled with `mcounteren.HPM19` - <%- if ext?(:S) -%> - , `scounteren.HPM19` - <%- if ext?(:H) -%> - , and `hcounteren.HPM19` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM19` + <%- if ext?(:S) -%> + , `scounteren.HPM19` + <%- if ext?(:H) -%> + , and `hcounteren.HPM19` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM19`# .2+h! [.rotate]#`scounteren.HPM19`# .2+h! [.rotate]#`hcounteren.HPM19`# - 4+^.>h! `hpmcounter19` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM19`# .2+h! [.rotate]#`scounteren.HPM19`# .2+h! [.rotate]#`hcounteren.HPM19`# + 4+^.>h! `hpmcounter19` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM19`# .2+h! [.rotate]#`scounteren.HPM19`# - 2+^.>h! `hpmcounter19` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM19`# .2+h! [.rotate]#`scounteren.HPM19`# + 2+^.>h! `hpmcounter19` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM19`# - ^.>h! `hpmcounter19` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM19`# + ^.>h! `hpmcounter19` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter19.COUNT - description: Alias of `mhpmcounter19.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter19.COUNT + description: Alias of `mhpmcounter19.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM19 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM19 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM19 & CSR[scounteren].HPM19) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM19 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM19 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM19 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM19 & CSR[scounteren].HPM19) == 1'b0) && (CSR[mcounteren].HPM19 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM19 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM19 & CSR[scounteren].HPM19) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM19 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM19 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM19 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM19 & CSR[scounteren].HPM19) == 1'b0) && (CSR[mcounteren].HPM19 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM19 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(19); + return read_hpm_counter(19); diff --git a/arch/csr/Zihpm/hpmcounter19h.yaml b/arch/csr/Zihpm/hpmcounter19h.yaml index 4e8d45e4b..84f6a8339 100644 --- a/arch/csr/Zihpm/hpmcounter19h.yaml +++ b/arch/csr/Zihpm/hpmcounter19h.yaml @@ -4,70 +4,72 @@ -hpmcounter19h: - long_name: User-mode Hardware Performance Counter 16, high half - address: 0xC93 - description: | - Alias for M-mode CSR `mhpmcounter19h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter19h +long_name: User-mode Hardware Performance Counter 16, high half +address: 0xC93 +description: | + Alias for M-mode CSR `mhpmcounter19h`. - Privilege mode access is controlled with `mcounteren.HPM19`, `scounteren.HPM19`, and `hcounteren.HPM19` as follows: + Privilege mode access is controlled with `mcounteren.HPM19`, `scounteren.HPM19`, and `hcounteren.HPM19` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM19`# .2+h! [.rotate]#`scounteren.HPM19`# .2+h! [.rotate]#`hcounteren.HPM19`# - 4+^.>h! `hpmcounter19h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM19`# .2+h! [.rotate]#`scounteren.HPM19`# .2+h! [.rotate]#`hcounteren.HPM19`# + 4+^.>h! `hpmcounter19h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter19h.COUNT - description: Alias of `mhpmcounter19h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter19h.COUNT + description: Alias of `mhpmcounter19h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM19 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM19 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM19 & CSR[scounteren].HPM19) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM19 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM19 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM19 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM19 & CSR[scounteren].HPM19) == 1'b0) && (CSR[mcounteren].HPM19 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM19 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM19 & CSR[scounteren].HPM19) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM19 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM19 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM19 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM19 & CSR[scounteren].HPM19) == 1'b0) && (CSR[mcounteren].HPM19 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM19 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(19)[63:32]; + return read_hpm_counter(19)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter20.yaml b/arch/csr/Zihpm/hpmcounter20.yaml index fd7a916be..5db4a0a99 100644 --- a/arch/csr/Zihpm/hpmcounter20.yaml +++ b/arch/csr/Zihpm/hpmcounter20.yaml @@ -4,100 +4,102 @@ -hpmcounter20: - long_name: User-mode Hardware Performance Counter 17 - address: 0xC14 - description: | - Alias for M-mode CSR `mhpmcounter20`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter20 +long_name: User-mode Hardware Performance Counter 17 +address: 0xC14 +description: | + Alias for M-mode CSR `mhpmcounter20`. - Privilege mode access is controlled with `mcounteren.HPM20` - <%- if ext?(:S) -%> - , `scounteren.HPM20` - <%- if ext?(:H) -%> - , and `hcounteren.HPM20` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM20` + <%- if ext?(:S) -%> + , `scounteren.HPM20` + <%- if ext?(:H) -%> + , and `hcounteren.HPM20` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM20`# .2+h! [.rotate]#`scounteren.HPM20`# .2+h! [.rotate]#`hcounteren.HPM20`# - 4+^.>h! `hpmcounter20` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM20`# .2+h! [.rotate]#`scounteren.HPM20`# .2+h! [.rotate]#`hcounteren.HPM20`# + 4+^.>h! `hpmcounter20` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM20`# .2+h! [.rotate]#`scounteren.HPM20`# - 2+^.>h! `hpmcounter20` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM20`# .2+h! [.rotate]#`scounteren.HPM20`# + 2+^.>h! `hpmcounter20` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM20`# - ^.>h! `hpmcounter20` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM20`# + ^.>h! `hpmcounter20` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter20.COUNT - description: Alias of `mhpmcounter20.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter20.COUNT + description: Alias of `mhpmcounter20.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM20 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM20 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM20 & CSR[scounteren].HPM20) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM20 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM20 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM20 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM20 & CSR[scounteren].HPM20) == 1'b0) && (CSR[mcounteren].HPM20 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM20 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM20 & CSR[scounteren].HPM20) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM20 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM20 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM20 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM20 & CSR[scounteren].HPM20) == 1'b0) && (CSR[mcounteren].HPM20 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM20 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(20); + return read_hpm_counter(20); diff --git a/arch/csr/Zihpm/hpmcounter20h.yaml b/arch/csr/Zihpm/hpmcounter20h.yaml index d3a8d0912..692e695be 100644 --- a/arch/csr/Zihpm/hpmcounter20h.yaml +++ b/arch/csr/Zihpm/hpmcounter20h.yaml @@ -4,70 +4,72 @@ -hpmcounter20h: - long_name: User-mode Hardware Performance Counter 17, high half - address: 0xC94 - description: | - Alias for M-mode CSR `mhpmcounter20h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter20h +long_name: User-mode Hardware Performance Counter 17, high half +address: 0xC94 +description: | + Alias for M-mode CSR `mhpmcounter20h`. - Privilege mode access is controlled with `mcounteren.HPM20`, `scounteren.HPM20`, and `hcounteren.HPM20` as follows: + Privilege mode access is controlled with `mcounteren.HPM20`, `scounteren.HPM20`, and `hcounteren.HPM20` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM20`# .2+h! [.rotate]#`scounteren.HPM20`# .2+h! [.rotate]#`hcounteren.HPM20`# - 4+^.>h! `hpmcounter20h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM20`# .2+h! [.rotate]#`scounteren.HPM20`# .2+h! [.rotate]#`hcounteren.HPM20`# + 4+^.>h! `hpmcounter20h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter20h.COUNT - description: Alias of `mhpmcounter20h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter20h.COUNT + description: Alias of `mhpmcounter20h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM20 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM20 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM20 & CSR[scounteren].HPM20) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM20 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM20 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM20 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM20 & CSR[scounteren].HPM20) == 1'b0) && (CSR[mcounteren].HPM20 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM20 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM20 & CSR[scounteren].HPM20) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM20 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM20 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM20 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM20 & CSR[scounteren].HPM20) == 1'b0) && (CSR[mcounteren].HPM20 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM20 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(20)[63:32]; + return read_hpm_counter(20)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter21.yaml b/arch/csr/Zihpm/hpmcounter21.yaml index 9f184510a..ac6a44772 100644 --- a/arch/csr/Zihpm/hpmcounter21.yaml +++ b/arch/csr/Zihpm/hpmcounter21.yaml @@ -4,100 +4,102 @@ -hpmcounter21: - long_name: User-mode Hardware Performance Counter 18 - address: 0xC15 - description: | - Alias for M-mode CSR `mhpmcounter21`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter21 +long_name: User-mode Hardware Performance Counter 18 +address: 0xC15 +description: | + Alias for M-mode CSR `mhpmcounter21`. - Privilege mode access is controlled with `mcounteren.HPM21` - <%- if ext?(:S) -%> - , `scounteren.HPM21` - <%- if ext?(:H) -%> - , and `hcounteren.HPM21` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM21` + <%- if ext?(:S) -%> + , `scounteren.HPM21` + <%- if ext?(:H) -%> + , and `hcounteren.HPM21` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM21`# .2+h! [.rotate]#`scounteren.HPM21`# .2+h! [.rotate]#`hcounteren.HPM21`# - 4+^.>h! `hpmcounter21` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM21`# .2+h! [.rotate]#`scounteren.HPM21`# .2+h! [.rotate]#`hcounteren.HPM21`# + 4+^.>h! `hpmcounter21` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM21`# .2+h! [.rotate]#`scounteren.HPM21`# - 2+^.>h! `hpmcounter21` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM21`# .2+h! [.rotate]#`scounteren.HPM21`# + 2+^.>h! `hpmcounter21` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM21`# - ^.>h! `hpmcounter21` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM21`# + ^.>h! `hpmcounter21` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter21.COUNT - description: Alias of `mhpmcounter21.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter21.COUNT + description: Alias of `mhpmcounter21.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM21 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM21 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM21 & CSR[scounteren].HPM21) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM21 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM21 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM21 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM21 & CSR[scounteren].HPM21) == 1'b0) && (CSR[mcounteren].HPM21 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM21 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM21 & CSR[scounteren].HPM21) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM21 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM21 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM21 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM21 & CSR[scounteren].HPM21) == 1'b0) && (CSR[mcounteren].HPM21 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM21 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(21); + return read_hpm_counter(21); diff --git a/arch/csr/Zihpm/hpmcounter21h.yaml b/arch/csr/Zihpm/hpmcounter21h.yaml index ef76be018..6c6cd2838 100644 --- a/arch/csr/Zihpm/hpmcounter21h.yaml +++ b/arch/csr/Zihpm/hpmcounter21h.yaml @@ -4,70 +4,72 @@ -hpmcounter21h: - long_name: User-mode Hardware Performance Counter 18, high half - address: 0xC95 - description: | - Alias for M-mode CSR `mhpmcounter21h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter21h +long_name: User-mode Hardware Performance Counter 18, high half +address: 0xC95 +description: | + Alias for M-mode CSR `mhpmcounter21h`. - Privilege mode access is controlled with `mcounteren.HPM21`, `scounteren.HPM21`, and `hcounteren.HPM21` as follows: + Privilege mode access is controlled with `mcounteren.HPM21`, `scounteren.HPM21`, and `hcounteren.HPM21` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM21`# .2+h! [.rotate]#`scounteren.HPM21`# .2+h! [.rotate]#`hcounteren.HPM21`# - 4+^.>h! `hpmcounter21h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM21`# .2+h! [.rotate]#`scounteren.HPM21`# .2+h! [.rotate]#`hcounteren.HPM21`# + 4+^.>h! `hpmcounter21h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter21h.COUNT - description: Alias of `mhpmcounter21h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter21h.COUNT + description: Alias of `mhpmcounter21h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM21 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM21 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM21 & CSR[scounteren].HPM21) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM21 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM21 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM21 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM21 & CSR[scounteren].HPM21) == 1'b0) && (CSR[mcounteren].HPM21 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM21 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM21 & CSR[scounteren].HPM21) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM21 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM21 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM21 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM21 & CSR[scounteren].HPM21) == 1'b0) && (CSR[mcounteren].HPM21 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM21 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(21)[63:32]; + return read_hpm_counter(21)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter22.yaml b/arch/csr/Zihpm/hpmcounter22.yaml index b40f8056d..c422add0d 100644 --- a/arch/csr/Zihpm/hpmcounter22.yaml +++ b/arch/csr/Zihpm/hpmcounter22.yaml @@ -4,100 +4,102 @@ -hpmcounter22: - long_name: User-mode Hardware Performance Counter 19 - address: 0xC16 - description: | - Alias for M-mode CSR `mhpmcounter22`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter22 +long_name: User-mode Hardware Performance Counter 19 +address: 0xC16 +description: | + Alias for M-mode CSR `mhpmcounter22`. - Privilege mode access is controlled with `mcounteren.HPM22` - <%- if ext?(:S) -%> - , `scounteren.HPM22` - <%- if ext?(:H) -%> - , and `hcounteren.HPM22` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM22` + <%- if ext?(:S) -%> + , `scounteren.HPM22` + <%- if ext?(:H) -%> + , and `hcounteren.HPM22` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM22`# .2+h! [.rotate]#`scounteren.HPM22`# .2+h! [.rotate]#`hcounteren.HPM22`# - 4+^.>h! `hpmcounter22` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM22`# .2+h! [.rotate]#`scounteren.HPM22`# .2+h! [.rotate]#`hcounteren.HPM22`# + 4+^.>h! `hpmcounter22` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM22`# .2+h! [.rotate]#`scounteren.HPM22`# - 2+^.>h! `hpmcounter22` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM22`# .2+h! [.rotate]#`scounteren.HPM22`# + 2+^.>h! `hpmcounter22` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM22`# - ^.>h! `hpmcounter22` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM22`# + ^.>h! `hpmcounter22` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter22.COUNT - description: Alias of `mhpmcounter22.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter22.COUNT + description: Alias of `mhpmcounter22.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM22 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM22 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM22 & CSR[scounteren].HPM22) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM22 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM22 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM22 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM22 & CSR[scounteren].HPM22) == 1'b0) && (CSR[mcounteren].HPM22 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM22 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM22 & CSR[scounteren].HPM22) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM22 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM22 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM22 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM22 & CSR[scounteren].HPM22) == 1'b0) && (CSR[mcounteren].HPM22 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM22 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(22); + return read_hpm_counter(22); diff --git a/arch/csr/Zihpm/hpmcounter22h.yaml b/arch/csr/Zihpm/hpmcounter22h.yaml index c45c10901..f67e7df7a 100644 --- a/arch/csr/Zihpm/hpmcounter22h.yaml +++ b/arch/csr/Zihpm/hpmcounter22h.yaml @@ -4,70 +4,72 @@ -hpmcounter22h: - long_name: User-mode Hardware Performance Counter 19, high half - address: 0xC96 - description: | - Alias for M-mode CSR `mhpmcounter22h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter22h +long_name: User-mode Hardware Performance Counter 19, high half +address: 0xC96 +description: | + Alias for M-mode CSR `mhpmcounter22h`. - Privilege mode access is controlled with `mcounteren.HPM22`, `scounteren.HPM22`, and `hcounteren.HPM22` as follows: + Privilege mode access is controlled with `mcounteren.HPM22`, `scounteren.HPM22`, and `hcounteren.HPM22` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM22`# .2+h! [.rotate]#`scounteren.HPM22`# .2+h! [.rotate]#`hcounteren.HPM22`# - 4+^.>h! `hpmcounter22h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM22`# .2+h! [.rotate]#`scounteren.HPM22`# .2+h! [.rotate]#`hcounteren.HPM22`# + 4+^.>h! `hpmcounter22h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter22h.COUNT - description: Alias of `mhpmcounter22h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter22h.COUNT + description: Alias of `mhpmcounter22h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM22 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM22 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM22 & CSR[scounteren].HPM22) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM22 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM22 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM22 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM22 & CSR[scounteren].HPM22) == 1'b0) && (CSR[mcounteren].HPM22 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM22 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM22 & CSR[scounteren].HPM22) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM22 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM22 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM22 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM22 & CSR[scounteren].HPM22) == 1'b0) && (CSR[mcounteren].HPM22 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM22 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(22)[63:32]; + return read_hpm_counter(22)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter23.yaml b/arch/csr/Zihpm/hpmcounter23.yaml index 87414b84d..600270bd6 100644 --- a/arch/csr/Zihpm/hpmcounter23.yaml +++ b/arch/csr/Zihpm/hpmcounter23.yaml @@ -4,100 +4,102 @@ -hpmcounter23: - long_name: User-mode Hardware Performance Counter 20 - address: 0xC17 - description: | - Alias for M-mode CSR `mhpmcounter23`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter23 +long_name: User-mode Hardware Performance Counter 20 +address: 0xC17 +description: | + Alias for M-mode CSR `mhpmcounter23`. - Privilege mode access is controlled with `mcounteren.HPM23` - <%- if ext?(:S) -%> - , `scounteren.HPM23` - <%- if ext?(:H) -%> - , and `hcounteren.HPM23` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM23` + <%- if ext?(:S) -%> + , `scounteren.HPM23` + <%- if ext?(:H) -%> + , and `hcounteren.HPM23` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM23`# .2+h! [.rotate]#`scounteren.HPM23`# .2+h! [.rotate]#`hcounteren.HPM23`# - 4+^.>h! `hpmcounter23` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM23`# .2+h! [.rotate]#`scounteren.HPM23`# .2+h! [.rotate]#`hcounteren.HPM23`# + 4+^.>h! `hpmcounter23` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM23`# .2+h! [.rotate]#`scounteren.HPM23`# - 2+^.>h! `hpmcounter23` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM23`# .2+h! [.rotate]#`scounteren.HPM23`# + 2+^.>h! `hpmcounter23` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM23`# - ^.>h! `hpmcounter23` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM23`# + ^.>h! `hpmcounter23` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter23.COUNT - description: Alias of `mhpmcounter23.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter23.COUNT + description: Alias of `mhpmcounter23.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM23 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM23 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM23 & CSR[scounteren].HPM23) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM23 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM23 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM23 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM23 & CSR[scounteren].HPM23) == 1'b0) && (CSR[mcounteren].HPM23 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM23 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM23 & CSR[scounteren].HPM23) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM23 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM23 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM23 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM23 & CSR[scounteren].HPM23) == 1'b0) && (CSR[mcounteren].HPM23 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM23 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(23); + return read_hpm_counter(23); diff --git a/arch/csr/Zihpm/hpmcounter23h.yaml b/arch/csr/Zihpm/hpmcounter23h.yaml index 33c7fc76f..fab756b4c 100644 --- a/arch/csr/Zihpm/hpmcounter23h.yaml +++ b/arch/csr/Zihpm/hpmcounter23h.yaml @@ -4,70 +4,72 @@ -hpmcounter23h: - long_name: User-mode Hardware Performance Counter 20, high half - address: 0xC97 - description: | - Alias for M-mode CSR `mhpmcounter23h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter23h +long_name: User-mode Hardware Performance Counter 20, high half +address: 0xC97 +description: | + Alias for M-mode CSR `mhpmcounter23h`. - Privilege mode access is controlled with `mcounteren.HPM23`, `scounteren.HPM23`, and `hcounteren.HPM23` as follows: + Privilege mode access is controlled with `mcounteren.HPM23`, `scounteren.HPM23`, and `hcounteren.HPM23` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM23`# .2+h! [.rotate]#`scounteren.HPM23`# .2+h! [.rotate]#`hcounteren.HPM23`# - 4+^.>h! `hpmcounter23h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM23`# .2+h! [.rotate]#`scounteren.HPM23`# .2+h! [.rotate]#`hcounteren.HPM23`# + 4+^.>h! `hpmcounter23h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter23h.COUNT - description: Alias of `mhpmcounter23h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter23h.COUNT + description: Alias of `mhpmcounter23h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM23 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM23 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM23 & CSR[scounteren].HPM23) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM23 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM23 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM23 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM23 & CSR[scounteren].HPM23) == 1'b0) && (CSR[mcounteren].HPM23 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM23 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM23 & CSR[scounteren].HPM23) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM23 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM23 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM23 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM23 & CSR[scounteren].HPM23) == 1'b0) && (CSR[mcounteren].HPM23 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM23 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(23)[63:32]; + return read_hpm_counter(23)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter24.yaml b/arch/csr/Zihpm/hpmcounter24.yaml index 038e6b74f..e30a48ff4 100644 --- a/arch/csr/Zihpm/hpmcounter24.yaml +++ b/arch/csr/Zihpm/hpmcounter24.yaml @@ -4,100 +4,102 @@ -hpmcounter24: - long_name: User-mode Hardware Performance Counter 21 - address: 0xC18 - description: | - Alias for M-mode CSR `mhpmcounter24`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter24 +long_name: User-mode Hardware Performance Counter 21 +address: 0xC18 +description: | + Alias for M-mode CSR `mhpmcounter24`. - Privilege mode access is controlled with `mcounteren.HPM24` - <%- if ext?(:S) -%> - , `scounteren.HPM24` - <%- if ext?(:H) -%> - , and `hcounteren.HPM24` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM24` + <%- if ext?(:S) -%> + , `scounteren.HPM24` + <%- if ext?(:H) -%> + , and `hcounteren.HPM24` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM24`# .2+h! [.rotate]#`scounteren.HPM24`# .2+h! [.rotate]#`hcounteren.HPM24`# - 4+^.>h! `hpmcounter24` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM24`# .2+h! [.rotate]#`scounteren.HPM24`# .2+h! [.rotate]#`hcounteren.HPM24`# + 4+^.>h! `hpmcounter24` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM24`# .2+h! [.rotate]#`scounteren.HPM24`# - 2+^.>h! `hpmcounter24` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM24`# .2+h! [.rotate]#`scounteren.HPM24`# + 2+^.>h! `hpmcounter24` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM24`# - ^.>h! `hpmcounter24` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM24`# + ^.>h! `hpmcounter24` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter24.COUNT - description: Alias of `mhpmcounter24.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter24.COUNT + description: Alias of `mhpmcounter24.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM24 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM24 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM24 & CSR[scounteren].HPM24) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM24 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM24 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM24 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM24 & CSR[scounteren].HPM24) == 1'b0) && (CSR[mcounteren].HPM24 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM24 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM24 & CSR[scounteren].HPM24) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM24 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM24 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM24 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM24 & CSR[scounteren].HPM24) == 1'b0) && (CSR[mcounteren].HPM24 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM24 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(24); + return read_hpm_counter(24); diff --git a/arch/csr/Zihpm/hpmcounter24h.yaml b/arch/csr/Zihpm/hpmcounter24h.yaml index 530d0142f..9d255c1fa 100644 --- a/arch/csr/Zihpm/hpmcounter24h.yaml +++ b/arch/csr/Zihpm/hpmcounter24h.yaml @@ -4,70 +4,72 @@ -hpmcounter24h: - long_name: User-mode Hardware Performance Counter 21, high half - address: 0xC98 - description: | - Alias for M-mode CSR `mhpmcounter24h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter24h +long_name: User-mode Hardware Performance Counter 21, high half +address: 0xC98 +description: | + Alias for M-mode CSR `mhpmcounter24h`. - Privilege mode access is controlled with `mcounteren.HPM24`, `scounteren.HPM24`, and `hcounteren.HPM24` as follows: + Privilege mode access is controlled with `mcounteren.HPM24`, `scounteren.HPM24`, and `hcounteren.HPM24` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM24`# .2+h! [.rotate]#`scounteren.HPM24`# .2+h! [.rotate]#`hcounteren.HPM24`# - 4+^.>h! `hpmcounter24h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM24`# .2+h! [.rotate]#`scounteren.HPM24`# .2+h! [.rotate]#`hcounteren.HPM24`# + 4+^.>h! `hpmcounter24h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter24h.COUNT - description: Alias of `mhpmcounter24h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter24h.COUNT + description: Alias of `mhpmcounter24h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM24 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM24 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM24 & CSR[scounteren].HPM24) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM24 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM24 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM24 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM24 & CSR[scounteren].HPM24) == 1'b0) && (CSR[mcounteren].HPM24 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM24 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM24 & CSR[scounteren].HPM24) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM24 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM24 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM24 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM24 & CSR[scounteren].HPM24) == 1'b0) && (CSR[mcounteren].HPM24 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM24 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(24)[63:32]; + return read_hpm_counter(24)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter25.yaml b/arch/csr/Zihpm/hpmcounter25.yaml index 2e57b47d5..0022adae0 100644 --- a/arch/csr/Zihpm/hpmcounter25.yaml +++ b/arch/csr/Zihpm/hpmcounter25.yaml @@ -4,100 +4,102 @@ -hpmcounter25: - long_name: User-mode Hardware Performance Counter 22 - address: 0xC19 - description: | - Alias for M-mode CSR `mhpmcounter25`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter25 +long_name: User-mode Hardware Performance Counter 22 +address: 0xC19 +description: | + Alias for M-mode CSR `mhpmcounter25`. - Privilege mode access is controlled with `mcounteren.HPM25` - <%- if ext?(:S) -%> - , `scounteren.HPM25` - <%- if ext?(:H) -%> - , and `hcounteren.HPM25` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM25` + <%- if ext?(:S) -%> + , `scounteren.HPM25` + <%- if ext?(:H) -%> + , and `hcounteren.HPM25` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM25`# .2+h! [.rotate]#`scounteren.HPM25`# .2+h! [.rotate]#`hcounteren.HPM25`# - 4+^.>h! `hpmcounter25` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM25`# .2+h! [.rotate]#`scounteren.HPM25`# .2+h! [.rotate]#`hcounteren.HPM25`# + 4+^.>h! `hpmcounter25` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM25`# .2+h! [.rotate]#`scounteren.HPM25`# - 2+^.>h! `hpmcounter25` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM25`# .2+h! [.rotate]#`scounteren.HPM25`# + 2+^.>h! `hpmcounter25` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM25`# - ^.>h! `hpmcounter25` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM25`# + ^.>h! `hpmcounter25` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter25.COUNT - description: Alias of `mhpmcounter25.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter25.COUNT + description: Alias of `mhpmcounter25.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM25 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM25 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM25 & CSR[scounteren].HPM25) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM25 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM25 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM25 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM25 & CSR[scounteren].HPM25) == 1'b0) && (CSR[mcounteren].HPM25 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM25 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM25 & CSR[scounteren].HPM25) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM25 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM25 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM25 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM25 & CSR[scounteren].HPM25) == 1'b0) && (CSR[mcounteren].HPM25 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM25 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(25); + return read_hpm_counter(25); diff --git a/arch/csr/Zihpm/hpmcounter25h.yaml b/arch/csr/Zihpm/hpmcounter25h.yaml index 6272bcbb3..a91731b4b 100644 --- a/arch/csr/Zihpm/hpmcounter25h.yaml +++ b/arch/csr/Zihpm/hpmcounter25h.yaml @@ -4,70 +4,72 @@ -hpmcounter25h: - long_name: User-mode Hardware Performance Counter 22, high half - address: 0xC99 - description: | - Alias for M-mode CSR `mhpmcounter25h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter25h +long_name: User-mode Hardware Performance Counter 22, high half +address: 0xC99 +description: | + Alias for M-mode CSR `mhpmcounter25h`. - Privilege mode access is controlled with `mcounteren.HPM25`, `scounteren.HPM25`, and `hcounteren.HPM25` as follows: + Privilege mode access is controlled with `mcounteren.HPM25`, `scounteren.HPM25`, and `hcounteren.HPM25` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM25`# .2+h! [.rotate]#`scounteren.HPM25`# .2+h! [.rotate]#`hcounteren.HPM25`# - 4+^.>h! `hpmcounter25h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM25`# .2+h! [.rotate]#`scounteren.HPM25`# .2+h! [.rotate]#`hcounteren.HPM25`# + 4+^.>h! `hpmcounter25h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter25h.COUNT - description: Alias of `mhpmcounter25h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter25h.COUNT + description: Alias of `mhpmcounter25h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM25 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM25 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM25 & CSR[scounteren].HPM25) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM25 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM25 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM25 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM25 & CSR[scounteren].HPM25) == 1'b0) && (CSR[mcounteren].HPM25 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM25 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM25 & CSR[scounteren].HPM25) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM25 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM25 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM25 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM25 & CSR[scounteren].HPM25) == 1'b0) && (CSR[mcounteren].HPM25 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM25 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(25)[63:32]; + return read_hpm_counter(25)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter26.yaml b/arch/csr/Zihpm/hpmcounter26.yaml index 72281cc56..e018ddd3e 100644 --- a/arch/csr/Zihpm/hpmcounter26.yaml +++ b/arch/csr/Zihpm/hpmcounter26.yaml @@ -4,100 +4,102 @@ -hpmcounter26: - long_name: User-mode Hardware Performance Counter 23 - address: 0xC1A - description: | - Alias for M-mode CSR `mhpmcounter26`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter26 +long_name: User-mode Hardware Performance Counter 23 +address: 0xC1A +description: | + Alias for M-mode CSR `mhpmcounter26`. - Privilege mode access is controlled with `mcounteren.HPM26` - <%- if ext?(:S) -%> - , `scounteren.HPM26` - <%- if ext?(:H) -%> - , and `hcounteren.HPM26` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM26` + <%- if ext?(:S) -%> + , `scounteren.HPM26` + <%- if ext?(:H) -%> + , and `hcounteren.HPM26` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM26`# .2+h! [.rotate]#`scounteren.HPM26`# .2+h! [.rotate]#`hcounteren.HPM26`# - 4+^.>h! `hpmcounter26` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM26`# .2+h! [.rotate]#`scounteren.HPM26`# .2+h! [.rotate]#`hcounteren.HPM26`# + 4+^.>h! `hpmcounter26` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM26`# .2+h! [.rotate]#`scounteren.HPM26`# - 2+^.>h! `hpmcounter26` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM26`# .2+h! [.rotate]#`scounteren.HPM26`# + 2+^.>h! `hpmcounter26` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM26`# - ^.>h! `hpmcounter26` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM26`# + ^.>h! `hpmcounter26` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter26.COUNT - description: Alias of `mhpmcounter26.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter26.COUNT + description: Alias of `mhpmcounter26.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM26 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM26 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM26 & CSR[scounteren].HPM26) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM26 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM26 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM26 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM26 & CSR[scounteren].HPM26) == 1'b0) && (CSR[mcounteren].HPM26 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM26 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM26 & CSR[scounteren].HPM26) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM26 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM26 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM26 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM26 & CSR[scounteren].HPM26) == 1'b0) && (CSR[mcounteren].HPM26 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM26 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(26); + return read_hpm_counter(26); diff --git a/arch/csr/Zihpm/hpmcounter26h.yaml b/arch/csr/Zihpm/hpmcounter26h.yaml index a95da6fad..439495746 100644 --- a/arch/csr/Zihpm/hpmcounter26h.yaml +++ b/arch/csr/Zihpm/hpmcounter26h.yaml @@ -4,70 +4,72 @@ -hpmcounter26h: - long_name: User-mode Hardware Performance Counter 23, high half - address: 0xC9A - description: | - Alias for M-mode CSR `mhpmcounter26h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter26h +long_name: User-mode Hardware Performance Counter 23, high half +address: 0xC9A +description: | + Alias for M-mode CSR `mhpmcounter26h`. - Privilege mode access is controlled with `mcounteren.HPM26`, `scounteren.HPM26`, and `hcounteren.HPM26` as follows: + Privilege mode access is controlled with `mcounteren.HPM26`, `scounteren.HPM26`, and `hcounteren.HPM26` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM26`# .2+h! [.rotate]#`scounteren.HPM26`# .2+h! [.rotate]#`hcounteren.HPM26`# - 4+^.>h! `hpmcounter26h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM26`# .2+h! [.rotate]#`scounteren.HPM26`# .2+h! [.rotate]#`hcounteren.HPM26`# + 4+^.>h! `hpmcounter26h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter26h.COUNT - description: Alias of `mhpmcounter26h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter26h.COUNT + description: Alias of `mhpmcounter26h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM26 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM26 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM26 & CSR[scounteren].HPM26) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM26 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM26 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM26 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM26 & CSR[scounteren].HPM26) == 1'b0) && (CSR[mcounteren].HPM26 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM26 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM26 & CSR[scounteren].HPM26) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM26 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM26 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM26 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM26 & CSR[scounteren].HPM26) == 1'b0) && (CSR[mcounteren].HPM26 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM26 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(26)[63:32]; + return read_hpm_counter(26)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter27.yaml b/arch/csr/Zihpm/hpmcounter27.yaml index 238e04b9a..f4c4bfa21 100644 --- a/arch/csr/Zihpm/hpmcounter27.yaml +++ b/arch/csr/Zihpm/hpmcounter27.yaml @@ -4,100 +4,102 @@ -hpmcounter27: - long_name: User-mode Hardware Performance Counter 24 - address: 0xC1B - description: | - Alias for M-mode CSR `mhpmcounter27`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter27 +long_name: User-mode Hardware Performance Counter 24 +address: 0xC1B +description: | + Alias for M-mode CSR `mhpmcounter27`. - Privilege mode access is controlled with `mcounteren.HPM27` - <%- if ext?(:S) -%> - , `scounteren.HPM27` - <%- if ext?(:H) -%> - , and `hcounteren.HPM27` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM27` + <%- if ext?(:S) -%> + , `scounteren.HPM27` + <%- if ext?(:H) -%> + , and `hcounteren.HPM27` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM27`# .2+h! [.rotate]#`scounteren.HPM27`# .2+h! [.rotate]#`hcounteren.HPM27`# - 4+^.>h! `hpmcounter27` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM27`# .2+h! [.rotate]#`scounteren.HPM27`# .2+h! [.rotate]#`hcounteren.HPM27`# + 4+^.>h! `hpmcounter27` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM27`# .2+h! [.rotate]#`scounteren.HPM27`# - 2+^.>h! `hpmcounter27` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM27`# .2+h! [.rotate]#`scounteren.HPM27`# + 2+^.>h! `hpmcounter27` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM27`# - ^.>h! `hpmcounter27` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM27`# + ^.>h! `hpmcounter27` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter27.COUNT - description: Alias of `mhpmcounter27.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter27.COUNT + description: Alias of `mhpmcounter27.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM27 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM27 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM27 & CSR[scounteren].HPM27) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM27 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM27 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM27 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM27 & CSR[scounteren].HPM27) == 1'b0) && (CSR[mcounteren].HPM27 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM27 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM27 & CSR[scounteren].HPM27) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM27 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM27 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM27 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM27 & CSR[scounteren].HPM27) == 1'b0) && (CSR[mcounteren].HPM27 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM27 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(27); + return read_hpm_counter(27); diff --git a/arch/csr/Zihpm/hpmcounter27h.yaml b/arch/csr/Zihpm/hpmcounter27h.yaml index 08dc69800..77ebfae20 100644 --- a/arch/csr/Zihpm/hpmcounter27h.yaml +++ b/arch/csr/Zihpm/hpmcounter27h.yaml @@ -4,70 +4,72 @@ -hpmcounter27h: - long_name: User-mode Hardware Performance Counter 24, high half - address: 0xC9B - description: | - Alias for M-mode CSR `mhpmcounter27h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter27h +long_name: User-mode Hardware Performance Counter 24, high half +address: 0xC9B +description: | + Alias for M-mode CSR `mhpmcounter27h`. - Privilege mode access is controlled with `mcounteren.HPM27`, `scounteren.HPM27`, and `hcounteren.HPM27` as follows: + Privilege mode access is controlled with `mcounteren.HPM27`, `scounteren.HPM27`, and `hcounteren.HPM27` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM27`# .2+h! [.rotate]#`scounteren.HPM27`# .2+h! [.rotate]#`hcounteren.HPM27`# - 4+^.>h! `hpmcounter27h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM27`# .2+h! [.rotate]#`scounteren.HPM27`# .2+h! [.rotate]#`hcounteren.HPM27`# + 4+^.>h! `hpmcounter27h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter27h.COUNT - description: Alias of `mhpmcounter27h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter27h.COUNT + description: Alias of `mhpmcounter27h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM27 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM27 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM27 & CSR[scounteren].HPM27) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM27 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM27 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM27 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM27 & CSR[scounteren].HPM27) == 1'b0) && (CSR[mcounteren].HPM27 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM27 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM27 & CSR[scounteren].HPM27) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM27 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM27 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM27 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM27 & CSR[scounteren].HPM27) == 1'b0) && (CSR[mcounteren].HPM27 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM27 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(27)[63:32]; + return read_hpm_counter(27)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter28.yaml b/arch/csr/Zihpm/hpmcounter28.yaml index a666a253a..04e32bed2 100644 --- a/arch/csr/Zihpm/hpmcounter28.yaml +++ b/arch/csr/Zihpm/hpmcounter28.yaml @@ -4,100 +4,102 @@ -hpmcounter28: - long_name: User-mode Hardware Performance Counter 25 - address: 0xC1C - description: | - Alias for M-mode CSR `mhpmcounter28`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter28 +long_name: User-mode Hardware Performance Counter 25 +address: 0xC1C +description: | + Alias for M-mode CSR `mhpmcounter28`. - Privilege mode access is controlled with `mcounteren.HPM28` - <%- if ext?(:S) -%> - , `scounteren.HPM28` - <%- if ext?(:H) -%> - , and `hcounteren.HPM28` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM28` + <%- if ext?(:S) -%> + , `scounteren.HPM28` + <%- if ext?(:H) -%> + , and `hcounteren.HPM28` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM28`# .2+h! [.rotate]#`scounteren.HPM28`# .2+h! [.rotate]#`hcounteren.HPM28`# - 4+^.>h! `hpmcounter28` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM28`# .2+h! [.rotate]#`scounteren.HPM28`# .2+h! [.rotate]#`hcounteren.HPM28`# + 4+^.>h! `hpmcounter28` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM28`# .2+h! [.rotate]#`scounteren.HPM28`# - 2+^.>h! `hpmcounter28` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM28`# .2+h! [.rotate]#`scounteren.HPM28`# + 2+^.>h! `hpmcounter28` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM28`# - ^.>h! `hpmcounter28` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM28`# + ^.>h! `hpmcounter28` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter28.COUNT - description: Alias of `mhpmcounter28.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter28.COUNT + description: Alias of `mhpmcounter28.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM28 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM28 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM28 & CSR[scounteren].HPM28) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM28 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM28 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM28 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM28 & CSR[scounteren].HPM28) == 1'b0) && (CSR[mcounteren].HPM28 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM28 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM28 & CSR[scounteren].HPM28) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM28 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM28 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM28 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM28 & CSR[scounteren].HPM28) == 1'b0) && (CSR[mcounteren].HPM28 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM28 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(28); + return read_hpm_counter(28); diff --git a/arch/csr/Zihpm/hpmcounter28h.yaml b/arch/csr/Zihpm/hpmcounter28h.yaml index 4fab76e02..bd79376a8 100644 --- a/arch/csr/Zihpm/hpmcounter28h.yaml +++ b/arch/csr/Zihpm/hpmcounter28h.yaml @@ -4,70 +4,72 @@ -hpmcounter28h: - long_name: User-mode Hardware Performance Counter 25, high half - address: 0xC9C - description: | - Alias for M-mode CSR `mhpmcounter28h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter28h +long_name: User-mode Hardware Performance Counter 25, high half +address: 0xC9C +description: | + Alias for M-mode CSR `mhpmcounter28h`. - Privilege mode access is controlled with `mcounteren.HPM28`, `scounteren.HPM28`, and `hcounteren.HPM28` as follows: + Privilege mode access is controlled with `mcounteren.HPM28`, `scounteren.HPM28`, and `hcounteren.HPM28` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM28`# .2+h! [.rotate]#`scounteren.HPM28`# .2+h! [.rotate]#`hcounteren.HPM28`# - 4+^.>h! `hpmcounter28h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM28`# .2+h! [.rotate]#`scounteren.HPM28`# .2+h! [.rotate]#`hcounteren.HPM28`# + 4+^.>h! `hpmcounter28h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter28h.COUNT - description: Alias of `mhpmcounter28h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter28h.COUNT + description: Alias of `mhpmcounter28h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM28 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM28 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM28 & CSR[scounteren].HPM28) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM28 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM28 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM28 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM28 & CSR[scounteren].HPM28) == 1'b0) && (CSR[mcounteren].HPM28 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM28 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM28 & CSR[scounteren].HPM28) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM28 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM28 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM28 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM28 & CSR[scounteren].HPM28) == 1'b0) && (CSR[mcounteren].HPM28 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM28 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(28)[63:32]; + return read_hpm_counter(28)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter29.yaml b/arch/csr/Zihpm/hpmcounter29.yaml index d2b027747..504ce545a 100644 --- a/arch/csr/Zihpm/hpmcounter29.yaml +++ b/arch/csr/Zihpm/hpmcounter29.yaml @@ -4,100 +4,102 @@ -hpmcounter29: - long_name: User-mode Hardware Performance Counter 26 - address: 0xC1D - description: | - Alias for M-mode CSR `mhpmcounter29`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter29 +long_name: User-mode Hardware Performance Counter 26 +address: 0xC1D +description: | + Alias for M-mode CSR `mhpmcounter29`. - Privilege mode access is controlled with `mcounteren.HPM29` - <%- if ext?(:S) -%> - , `scounteren.HPM29` - <%- if ext?(:H) -%> - , and `hcounteren.HPM29` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM29` + <%- if ext?(:S) -%> + , `scounteren.HPM29` + <%- if ext?(:H) -%> + , and `hcounteren.HPM29` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM29`# .2+h! [.rotate]#`scounteren.HPM29`# .2+h! [.rotate]#`hcounteren.HPM29`# - 4+^.>h! `hpmcounter29` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM29`# .2+h! [.rotate]#`scounteren.HPM29`# .2+h! [.rotate]#`hcounteren.HPM29`# + 4+^.>h! `hpmcounter29` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM29`# .2+h! [.rotate]#`scounteren.HPM29`# - 2+^.>h! `hpmcounter29` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM29`# .2+h! [.rotate]#`scounteren.HPM29`# + 2+^.>h! `hpmcounter29` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM29`# - ^.>h! `hpmcounter29` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM29`# + ^.>h! `hpmcounter29` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter29.COUNT - description: Alias of `mhpmcounter29.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter29.COUNT + description: Alias of `mhpmcounter29.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM29 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM29 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM29 & CSR[scounteren].HPM29) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM29 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM29 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM29 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM29 & CSR[scounteren].HPM29) == 1'b0) && (CSR[mcounteren].HPM29 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM29 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM29 & CSR[scounteren].HPM29) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM29 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM29 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM29 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM29 & CSR[scounteren].HPM29) == 1'b0) && (CSR[mcounteren].HPM29 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM29 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(29); + return read_hpm_counter(29); diff --git a/arch/csr/Zihpm/hpmcounter29h.yaml b/arch/csr/Zihpm/hpmcounter29h.yaml index 13c6a2f3d..708c0095b 100644 --- a/arch/csr/Zihpm/hpmcounter29h.yaml +++ b/arch/csr/Zihpm/hpmcounter29h.yaml @@ -4,70 +4,72 @@ -hpmcounter29h: - long_name: User-mode Hardware Performance Counter 26, high half - address: 0xC9D - description: | - Alias for M-mode CSR `mhpmcounter29h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter29h +long_name: User-mode Hardware Performance Counter 26, high half +address: 0xC9D +description: | + Alias for M-mode CSR `mhpmcounter29h`. - Privilege mode access is controlled with `mcounteren.HPM29`, `scounteren.HPM29`, and `hcounteren.HPM29` as follows: + Privilege mode access is controlled with `mcounteren.HPM29`, `scounteren.HPM29`, and `hcounteren.HPM29` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM29`# .2+h! [.rotate]#`scounteren.HPM29`# .2+h! [.rotate]#`hcounteren.HPM29`# - 4+^.>h! `hpmcounter29h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM29`# .2+h! [.rotate]#`scounteren.HPM29`# .2+h! [.rotate]#`hcounteren.HPM29`# + 4+^.>h! `hpmcounter29h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter29h.COUNT - description: Alias of `mhpmcounter29h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter29h.COUNT + description: Alias of `mhpmcounter29h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM29 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM29 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM29 & CSR[scounteren].HPM29) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM29 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM29 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM29 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM29 & CSR[scounteren].HPM29) == 1'b0) && (CSR[mcounteren].HPM29 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM29 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM29 & CSR[scounteren].HPM29) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM29 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM29 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM29 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM29 & CSR[scounteren].HPM29) == 1'b0) && (CSR[mcounteren].HPM29 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM29 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(29)[63:32]; + return read_hpm_counter(29)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter3.yaml b/arch/csr/Zihpm/hpmcounter3.yaml index 5effc68fa..e0ef755ed 100644 --- a/arch/csr/Zihpm/hpmcounter3.yaml +++ b/arch/csr/Zihpm/hpmcounter3.yaml @@ -4,100 +4,102 @@ -hpmcounter3: - long_name: User-mode Hardware Performance Counter 0 - address: 0xC03 - description: | - Alias for M-mode CSR `mhpmcounter3`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter3 +long_name: User-mode Hardware Performance Counter 0 +address: 0xC03 +description: | + Alias for M-mode CSR `mhpmcounter3`. - Privilege mode access is controlled with `mcounteren.HPM3` - <%- if ext?(:S) -%> - , `scounteren.HPM3` - <%- if ext?(:H) -%> - , and `hcounteren.HPM3` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM3` + <%- if ext?(:S) -%> + , `scounteren.HPM3` + <%- if ext?(:H) -%> + , and `hcounteren.HPM3` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM3`# .2+h! [.rotate]#`scounteren.HPM3`# .2+h! [.rotate]#`hcounteren.HPM3`# - 4+^.>h! `hpmcounter3` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM3`# .2+h! [.rotate]#`scounteren.HPM3`# .2+h! [.rotate]#`hcounteren.HPM3`# + 4+^.>h! `hpmcounter3` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM3`# .2+h! [.rotate]#`scounteren.HPM3`# - 2+^.>h! `hpmcounter3` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM3`# .2+h! [.rotate]#`scounteren.HPM3`# + 2+^.>h! `hpmcounter3` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM3`# - ^.>h! `hpmcounter3` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM3`# + ^.>h! `hpmcounter3` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter3.COUNT - description: Alias of `mhpmcounter3.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter3.COUNT + description: Alias of `mhpmcounter3.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM3 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM3 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM3 & CSR[scounteren].HPM3) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM3 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM3 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM3 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM3 & CSR[scounteren].HPM3) == 1'b0) && (CSR[mcounteren].HPM3 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM3 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM3 & CSR[scounteren].HPM3) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM3 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM3 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM3 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM3 & CSR[scounteren].HPM3) == 1'b0) && (CSR[mcounteren].HPM3 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM3 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(3); + return read_hpm_counter(3); diff --git a/arch/csr/Zihpm/hpmcounter30.yaml b/arch/csr/Zihpm/hpmcounter30.yaml index 421825629..205e9d6f9 100644 --- a/arch/csr/Zihpm/hpmcounter30.yaml +++ b/arch/csr/Zihpm/hpmcounter30.yaml @@ -4,100 +4,102 @@ -hpmcounter30: - long_name: User-mode Hardware Performance Counter 27 - address: 0xC1E - description: | - Alias for M-mode CSR `mhpmcounter30`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter30 +long_name: User-mode Hardware Performance Counter 27 +address: 0xC1E +description: | + Alias for M-mode CSR `mhpmcounter30`. - Privilege mode access is controlled with `mcounteren.HPM30` - <%- if ext?(:S) -%> - , `scounteren.HPM30` - <%- if ext?(:H) -%> - , and `hcounteren.HPM30` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM30` + <%- if ext?(:S) -%> + , `scounteren.HPM30` + <%- if ext?(:H) -%> + , and `hcounteren.HPM30` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM30`# .2+h! [.rotate]#`scounteren.HPM30`# .2+h! [.rotate]#`hcounteren.HPM30`# - 4+^.>h! `hpmcounter30` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM30`# .2+h! [.rotate]#`scounteren.HPM30`# .2+h! [.rotate]#`hcounteren.HPM30`# + 4+^.>h! `hpmcounter30` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM30`# .2+h! [.rotate]#`scounteren.HPM30`# - 2+^.>h! `hpmcounter30` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM30`# .2+h! [.rotate]#`scounteren.HPM30`# + 2+^.>h! `hpmcounter30` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM30`# - ^.>h! `hpmcounter30` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM30`# + ^.>h! `hpmcounter30` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter30.COUNT - description: Alias of `mhpmcounter30.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter30.COUNT + description: Alias of `mhpmcounter30.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM30 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM30 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM30 & CSR[scounteren].HPM30) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM30 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM30 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM30 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM30 & CSR[scounteren].HPM30) == 1'b0) && (CSR[mcounteren].HPM30 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM30 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM30 & CSR[scounteren].HPM30) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM30 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM30 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM30 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM30 & CSR[scounteren].HPM30) == 1'b0) && (CSR[mcounteren].HPM30 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM30 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(30); + return read_hpm_counter(30); diff --git a/arch/csr/Zihpm/hpmcounter30h.yaml b/arch/csr/Zihpm/hpmcounter30h.yaml index abbda24ee..f80aca0db 100644 --- a/arch/csr/Zihpm/hpmcounter30h.yaml +++ b/arch/csr/Zihpm/hpmcounter30h.yaml @@ -4,70 +4,72 @@ -hpmcounter30h: - long_name: User-mode Hardware Performance Counter 27, high half - address: 0xC9E - description: | - Alias for M-mode CSR `mhpmcounter30h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter30h +long_name: User-mode Hardware Performance Counter 27, high half +address: 0xC9E +description: | + Alias for M-mode CSR `mhpmcounter30h`. - Privilege mode access is controlled with `mcounteren.HPM30`, `scounteren.HPM30`, and `hcounteren.HPM30` as follows: + Privilege mode access is controlled with `mcounteren.HPM30`, `scounteren.HPM30`, and `hcounteren.HPM30` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM30`# .2+h! [.rotate]#`scounteren.HPM30`# .2+h! [.rotate]#`hcounteren.HPM30`# - 4+^.>h! `hpmcounter30h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM30`# .2+h! [.rotate]#`scounteren.HPM30`# .2+h! [.rotate]#`hcounteren.HPM30`# + 4+^.>h! `hpmcounter30h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter30h.COUNT - description: Alias of `mhpmcounter30h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter30h.COUNT + description: Alias of `mhpmcounter30h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM30 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM30 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM30 & CSR[scounteren].HPM30) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM30 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM30 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM30 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM30 & CSR[scounteren].HPM30) == 1'b0) && (CSR[mcounteren].HPM30 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM30 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM30 & CSR[scounteren].HPM30) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM30 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM30 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM30 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM30 & CSR[scounteren].HPM30) == 1'b0) && (CSR[mcounteren].HPM30 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM30 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(30)[63:32]; + return read_hpm_counter(30)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter31.yaml b/arch/csr/Zihpm/hpmcounter31.yaml index a77960f60..8682dd896 100644 --- a/arch/csr/Zihpm/hpmcounter31.yaml +++ b/arch/csr/Zihpm/hpmcounter31.yaml @@ -4,100 +4,102 @@ -hpmcounter31: - long_name: User-mode Hardware Performance Counter 28 - address: 0xC1F - description: | - Alias for M-mode CSR `mhpmcounter31`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter31 +long_name: User-mode Hardware Performance Counter 28 +address: 0xC1F +description: | + Alias for M-mode CSR `mhpmcounter31`. - Privilege mode access is controlled with `mcounteren.HPM31` - <%- if ext?(:S) -%> - , `scounteren.HPM31` - <%- if ext?(:H) -%> - , and `hcounteren.HPM31` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM31` + <%- if ext?(:S) -%> + , `scounteren.HPM31` + <%- if ext?(:H) -%> + , and `hcounteren.HPM31` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM31`# .2+h! [.rotate]#`scounteren.HPM31`# .2+h! [.rotate]#`hcounteren.HPM31`# - 4+^.>h! `hpmcounter31` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM31`# .2+h! [.rotate]#`scounteren.HPM31`# .2+h! [.rotate]#`hcounteren.HPM31`# + 4+^.>h! `hpmcounter31` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM31`# .2+h! [.rotate]#`scounteren.HPM31`# - 2+^.>h! `hpmcounter31` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM31`# .2+h! [.rotate]#`scounteren.HPM31`# + 2+^.>h! `hpmcounter31` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM31`# - ^.>h! `hpmcounter31` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM31`# + ^.>h! `hpmcounter31` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter31.COUNT - description: Alias of `mhpmcounter31.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter31.COUNT + description: Alias of `mhpmcounter31.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM31 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM31 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM31 & CSR[scounteren].HPM31) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM31 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM31 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM31 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM31 & CSR[scounteren].HPM31) == 1'b0) && (CSR[mcounteren].HPM31 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM31 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM31 & CSR[scounteren].HPM31) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM31 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM31 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM31 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM31 & CSR[scounteren].HPM31) == 1'b0) && (CSR[mcounteren].HPM31 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM31 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(31); + return read_hpm_counter(31); diff --git a/arch/csr/Zihpm/hpmcounter31h.yaml b/arch/csr/Zihpm/hpmcounter31h.yaml index 1a9c33fd6..b84202355 100644 --- a/arch/csr/Zihpm/hpmcounter31h.yaml +++ b/arch/csr/Zihpm/hpmcounter31h.yaml @@ -4,70 +4,72 @@ -hpmcounter31h: - long_name: User-mode Hardware Performance Counter 28, high half - address: 0xC9F - description: | - Alias for M-mode CSR `mhpmcounter31h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter31h +long_name: User-mode Hardware Performance Counter 28, high half +address: 0xC9F +description: | + Alias for M-mode CSR `mhpmcounter31h`. - Privilege mode access is controlled with `mcounteren.HPM31`, `scounteren.HPM31`, and `hcounteren.HPM31` as follows: + Privilege mode access is controlled with `mcounteren.HPM31`, `scounteren.HPM31`, and `hcounteren.HPM31` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM31`# .2+h! [.rotate]#`scounteren.HPM31`# .2+h! [.rotate]#`hcounteren.HPM31`# - 4+^.>h! `hpmcounter31h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM31`# .2+h! [.rotate]#`scounteren.HPM31`# .2+h! [.rotate]#`hcounteren.HPM31`# + 4+^.>h! `hpmcounter31h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter31h.COUNT - description: Alias of `mhpmcounter31h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter31h.COUNT + description: Alias of `mhpmcounter31h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM31 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM31 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM31 & CSR[scounteren].HPM31) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM31 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM31 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM31 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM31 & CSR[scounteren].HPM31) == 1'b0) && (CSR[mcounteren].HPM31 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM31 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM31 & CSR[scounteren].HPM31) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM31 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM31 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM31 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM31 & CSR[scounteren].HPM31) == 1'b0) && (CSR[mcounteren].HPM31 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM31 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(31)[63:32]; + return read_hpm_counter(31)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter3h.yaml b/arch/csr/Zihpm/hpmcounter3h.yaml index 67808e305..11acfe0f8 100644 --- a/arch/csr/Zihpm/hpmcounter3h.yaml +++ b/arch/csr/Zihpm/hpmcounter3h.yaml @@ -4,70 +4,72 @@ -hpmcounter3h: - long_name: User-mode Hardware Performance Counter 0, high half - address: 0xC83 - description: | - Alias for M-mode CSR `mhpmcounter3h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter3h +long_name: User-mode Hardware Performance Counter 0, high half +address: 0xC83 +description: | + Alias for M-mode CSR `mhpmcounter3h`. - Privilege mode access is controlled with `mcounteren.HPM3`, `scounteren.HPM3`, and `hcounteren.HPM3` as follows: + Privilege mode access is controlled with `mcounteren.HPM3`, `scounteren.HPM3`, and `hcounteren.HPM3` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM3`# .2+h! [.rotate]#`scounteren.HPM3`# .2+h! [.rotate]#`hcounteren.HPM3`# - 4+^.>h! `hpmcounter3h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM3`# .2+h! [.rotate]#`scounteren.HPM3`# .2+h! [.rotate]#`hcounteren.HPM3`# + 4+^.>h! `hpmcounter3h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter3h.COUNT - description: Alias of `mhpmcounter3h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter3h.COUNT + description: Alias of `mhpmcounter3h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM3 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM3 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM3 & CSR[scounteren].HPM3) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM3 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM3 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM3 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM3 & CSR[scounteren].HPM3) == 1'b0) && (CSR[mcounteren].HPM3 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM3 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM3 & CSR[scounteren].HPM3) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM3 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM3 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM3 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM3 & CSR[scounteren].HPM3) == 1'b0) && (CSR[mcounteren].HPM3 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM3 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(3)[63:32]; + return read_hpm_counter(3)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter4.yaml b/arch/csr/Zihpm/hpmcounter4.yaml index 75a8c78f6..0947a5f15 100644 --- a/arch/csr/Zihpm/hpmcounter4.yaml +++ b/arch/csr/Zihpm/hpmcounter4.yaml @@ -4,100 +4,102 @@ -hpmcounter4: - long_name: User-mode Hardware Performance Counter 1 - address: 0xC04 - description: | - Alias for M-mode CSR `mhpmcounter4`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter4 +long_name: User-mode Hardware Performance Counter 1 +address: 0xC04 +description: | + Alias for M-mode CSR `mhpmcounter4`. - Privilege mode access is controlled with `mcounteren.HPM4` - <%- if ext?(:S) -%> - , `scounteren.HPM4` - <%- if ext?(:H) -%> - , and `hcounteren.HPM4` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM4` + <%- if ext?(:S) -%> + , `scounteren.HPM4` + <%- if ext?(:H) -%> + , and `hcounteren.HPM4` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM4`# .2+h! [.rotate]#`scounteren.HPM4`# .2+h! [.rotate]#`hcounteren.HPM4`# - 4+^.>h! `hpmcounter4` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM4`# .2+h! [.rotate]#`scounteren.HPM4`# .2+h! [.rotate]#`hcounteren.HPM4`# + 4+^.>h! `hpmcounter4` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM4`# .2+h! [.rotate]#`scounteren.HPM4`# - 2+^.>h! `hpmcounter4` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM4`# .2+h! [.rotate]#`scounteren.HPM4`# + 2+^.>h! `hpmcounter4` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM4`# - ^.>h! `hpmcounter4` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM4`# + ^.>h! `hpmcounter4` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter4.COUNT - description: Alias of `mhpmcounter4.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter4.COUNT + description: Alias of `mhpmcounter4.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM4 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM4 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM4 & CSR[scounteren].HPM4) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM4 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM4 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM4 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM4 & CSR[scounteren].HPM4) == 1'b0) && (CSR[mcounteren].HPM4 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM4 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM4 & CSR[scounteren].HPM4) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM4 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM4 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM4 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM4 & CSR[scounteren].HPM4) == 1'b0) && (CSR[mcounteren].HPM4 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM4 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(4); + return read_hpm_counter(4); diff --git a/arch/csr/Zihpm/hpmcounter4h.yaml b/arch/csr/Zihpm/hpmcounter4h.yaml index 11e2cf6f4..b5920dd61 100644 --- a/arch/csr/Zihpm/hpmcounter4h.yaml +++ b/arch/csr/Zihpm/hpmcounter4h.yaml @@ -4,70 +4,72 @@ -hpmcounter4h: - long_name: User-mode Hardware Performance Counter 1, high half - address: 0xC84 - description: | - Alias for M-mode CSR `mhpmcounter4h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter4h +long_name: User-mode Hardware Performance Counter 1, high half +address: 0xC84 +description: | + Alias for M-mode CSR `mhpmcounter4h`. - Privilege mode access is controlled with `mcounteren.HPM4`, `scounteren.HPM4`, and `hcounteren.HPM4` as follows: + Privilege mode access is controlled with `mcounteren.HPM4`, `scounteren.HPM4`, and `hcounteren.HPM4` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM4`# .2+h! [.rotate]#`scounteren.HPM4`# .2+h! [.rotate]#`hcounteren.HPM4`# - 4+^.>h! `hpmcounter4h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM4`# .2+h! [.rotate]#`scounteren.HPM4`# .2+h! [.rotate]#`hcounteren.HPM4`# + 4+^.>h! `hpmcounter4h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter4h.COUNT - description: Alias of `mhpmcounter4h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter4h.COUNT + description: Alias of `mhpmcounter4h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM4 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM4 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM4 & CSR[scounteren].HPM4) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM4 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM4 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM4 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM4 & CSR[scounteren].HPM4) == 1'b0) && (CSR[mcounteren].HPM4 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM4 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM4 & CSR[scounteren].HPM4) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM4 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM4 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM4 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM4 & CSR[scounteren].HPM4) == 1'b0) && (CSR[mcounteren].HPM4 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM4 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(4)[63:32]; + return read_hpm_counter(4)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter5.yaml b/arch/csr/Zihpm/hpmcounter5.yaml index 13893d7d7..93c4ab78f 100644 --- a/arch/csr/Zihpm/hpmcounter5.yaml +++ b/arch/csr/Zihpm/hpmcounter5.yaml @@ -4,100 +4,102 @@ -hpmcounter5: - long_name: User-mode Hardware Performance Counter 2 - address: 0xC05 - description: | - Alias for M-mode CSR `mhpmcounter5`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter5 +long_name: User-mode Hardware Performance Counter 2 +address: 0xC05 +description: | + Alias for M-mode CSR `mhpmcounter5`. - Privilege mode access is controlled with `mcounteren.HPM5` - <%- if ext?(:S) -%> - , `scounteren.HPM5` - <%- if ext?(:H) -%> - , and `hcounteren.HPM5` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM5` + <%- if ext?(:S) -%> + , `scounteren.HPM5` + <%- if ext?(:H) -%> + , and `hcounteren.HPM5` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM5`# .2+h! [.rotate]#`scounteren.HPM5`# .2+h! [.rotate]#`hcounteren.HPM5`# - 4+^.>h! `hpmcounter5` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM5`# .2+h! [.rotate]#`scounteren.HPM5`# .2+h! [.rotate]#`hcounteren.HPM5`# + 4+^.>h! `hpmcounter5` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM5`# .2+h! [.rotate]#`scounteren.HPM5`# - 2+^.>h! `hpmcounter5` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM5`# .2+h! [.rotate]#`scounteren.HPM5`# + 2+^.>h! `hpmcounter5` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM5`# - ^.>h! `hpmcounter5` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM5`# + ^.>h! `hpmcounter5` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter5.COUNT - description: Alias of `mhpmcounter5.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter5.COUNT + description: Alias of `mhpmcounter5.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM5 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM5 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM5 & CSR[scounteren].HPM5) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM5 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM5 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM5 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM5 & CSR[scounteren].HPM5) == 1'b0) && (CSR[mcounteren].HPM5 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM5 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM5 & CSR[scounteren].HPM5) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM5 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM5 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM5 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM5 & CSR[scounteren].HPM5) == 1'b0) && (CSR[mcounteren].HPM5 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM5 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(5); + return read_hpm_counter(5); diff --git a/arch/csr/Zihpm/hpmcounter5h.yaml b/arch/csr/Zihpm/hpmcounter5h.yaml index cd3e942a5..f637926f6 100644 --- a/arch/csr/Zihpm/hpmcounter5h.yaml +++ b/arch/csr/Zihpm/hpmcounter5h.yaml @@ -4,70 +4,72 @@ -hpmcounter5h: - long_name: User-mode Hardware Performance Counter 2, high half - address: 0xC85 - description: | - Alias for M-mode CSR `mhpmcounter5h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter5h +long_name: User-mode Hardware Performance Counter 2, high half +address: 0xC85 +description: | + Alias for M-mode CSR `mhpmcounter5h`. - Privilege mode access is controlled with `mcounteren.HPM5`, `scounteren.HPM5`, and `hcounteren.HPM5` as follows: + Privilege mode access is controlled with `mcounteren.HPM5`, `scounteren.HPM5`, and `hcounteren.HPM5` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM5`# .2+h! [.rotate]#`scounteren.HPM5`# .2+h! [.rotate]#`hcounteren.HPM5`# - 4+^.>h! `hpmcounter5h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM5`# .2+h! [.rotate]#`scounteren.HPM5`# .2+h! [.rotate]#`hcounteren.HPM5`# + 4+^.>h! `hpmcounter5h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter5h.COUNT - description: Alias of `mhpmcounter5h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter5h.COUNT + description: Alias of `mhpmcounter5h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM5 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM5 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM5 & CSR[scounteren].HPM5) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM5 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM5 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM5 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM5 & CSR[scounteren].HPM5) == 1'b0) && (CSR[mcounteren].HPM5 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM5 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM5 & CSR[scounteren].HPM5) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM5 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM5 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM5 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM5 & CSR[scounteren].HPM5) == 1'b0) && (CSR[mcounteren].HPM5 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM5 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(5)[63:32]; + return read_hpm_counter(5)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter6.yaml b/arch/csr/Zihpm/hpmcounter6.yaml index 9e69420ab..ad2646d52 100644 --- a/arch/csr/Zihpm/hpmcounter6.yaml +++ b/arch/csr/Zihpm/hpmcounter6.yaml @@ -4,100 +4,102 @@ -hpmcounter6: - long_name: User-mode Hardware Performance Counter 3 - address: 0xC06 - description: | - Alias for M-mode CSR `mhpmcounter6`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter6 +long_name: User-mode Hardware Performance Counter 3 +address: 0xC06 +description: | + Alias for M-mode CSR `mhpmcounter6`. - Privilege mode access is controlled with `mcounteren.HPM6` - <%- if ext?(:S) -%> - , `scounteren.HPM6` - <%- if ext?(:H) -%> - , and `hcounteren.HPM6` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM6` + <%- if ext?(:S) -%> + , `scounteren.HPM6` + <%- if ext?(:H) -%> + , and `hcounteren.HPM6` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM6`# .2+h! [.rotate]#`scounteren.HPM6`# .2+h! [.rotate]#`hcounteren.HPM6`# - 4+^.>h! `hpmcounter6` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM6`# .2+h! [.rotate]#`scounteren.HPM6`# .2+h! [.rotate]#`hcounteren.HPM6`# + 4+^.>h! `hpmcounter6` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM6`# .2+h! [.rotate]#`scounteren.HPM6`# - 2+^.>h! `hpmcounter6` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM6`# .2+h! [.rotate]#`scounteren.HPM6`# + 2+^.>h! `hpmcounter6` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM6`# - ^.>h! `hpmcounter6` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM6`# + ^.>h! `hpmcounter6` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter6.COUNT - description: Alias of `mhpmcounter6.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter6.COUNT + description: Alias of `mhpmcounter6.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM6 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM6 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM6 & CSR[scounteren].HPM6) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM6 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM6 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM6 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM6 & CSR[scounteren].HPM6) == 1'b0) && (CSR[mcounteren].HPM6 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM6 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM6 & CSR[scounteren].HPM6) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM6 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM6 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM6 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM6 & CSR[scounteren].HPM6) == 1'b0) && (CSR[mcounteren].HPM6 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM6 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(6); + return read_hpm_counter(6); diff --git a/arch/csr/Zihpm/hpmcounter6h.yaml b/arch/csr/Zihpm/hpmcounter6h.yaml index 3404fc269..83996abc5 100644 --- a/arch/csr/Zihpm/hpmcounter6h.yaml +++ b/arch/csr/Zihpm/hpmcounter6h.yaml @@ -4,70 +4,72 @@ -hpmcounter6h: - long_name: User-mode Hardware Performance Counter 3, high half - address: 0xC86 - description: | - Alias for M-mode CSR `mhpmcounter6h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter6h +long_name: User-mode Hardware Performance Counter 3, high half +address: 0xC86 +description: | + Alias for M-mode CSR `mhpmcounter6h`. - Privilege mode access is controlled with `mcounteren.HPM6`, `scounteren.HPM6`, and `hcounteren.HPM6` as follows: + Privilege mode access is controlled with `mcounteren.HPM6`, `scounteren.HPM6`, and `hcounteren.HPM6` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM6`# .2+h! [.rotate]#`scounteren.HPM6`# .2+h! [.rotate]#`hcounteren.HPM6`# - 4+^.>h! `hpmcounter6h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM6`# .2+h! [.rotate]#`scounteren.HPM6`# .2+h! [.rotate]#`hcounteren.HPM6`# + 4+^.>h! `hpmcounter6h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter6h.COUNT - description: Alias of `mhpmcounter6h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter6h.COUNT + description: Alias of `mhpmcounter6h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM6 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM6 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM6 & CSR[scounteren].HPM6) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM6 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM6 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM6 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM6 & CSR[scounteren].HPM6) == 1'b0) && (CSR[mcounteren].HPM6 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM6 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM6 & CSR[scounteren].HPM6) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM6 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM6 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM6 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM6 & CSR[scounteren].HPM6) == 1'b0) && (CSR[mcounteren].HPM6 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM6 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(6)[63:32]; + return read_hpm_counter(6)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter7.yaml b/arch/csr/Zihpm/hpmcounter7.yaml index 9f1fcc6a8..103aa95ff 100644 --- a/arch/csr/Zihpm/hpmcounter7.yaml +++ b/arch/csr/Zihpm/hpmcounter7.yaml @@ -4,100 +4,102 @@ -hpmcounter7: - long_name: User-mode Hardware Performance Counter 4 - address: 0xC07 - description: | - Alias for M-mode CSR `mhpmcounter7`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter7 +long_name: User-mode Hardware Performance Counter 4 +address: 0xC07 +description: | + Alias for M-mode CSR `mhpmcounter7`. - Privilege mode access is controlled with `mcounteren.HPM7` - <%- if ext?(:S) -%> - , `scounteren.HPM7` - <%- if ext?(:H) -%> - , and `hcounteren.HPM7` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM7` + <%- if ext?(:S) -%> + , `scounteren.HPM7` + <%- if ext?(:H) -%> + , and `hcounteren.HPM7` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM7`# .2+h! [.rotate]#`scounteren.HPM7`# .2+h! [.rotate]#`hcounteren.HPM7`# - 4+^.>h! `hpmcounter7` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM7`# .2+h! [.rotate]#`scounteren.HPM7`# .2+h! [.rotate]#`hcounteren.HPM7`# + 4+^.>h! `hpmcounter7` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM7`# .2+h! [.rotate]#`scounteren.HPM7`# - 2+^.>h! `hpmcounter7` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM7`# .2+h! [.rotate]#`scounteren.HPM7`# + 2+^.>h! `hpmcounter7` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM7`# - ^.>h! `hpmcounter7` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM7`# + ^.>h! `hpmcounter7` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter7.COUNT - description: Alias of `mhpmcounter7.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter7.COUNT + description: Alias of `mhpmcounter7.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM7 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM7 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM7 & CSR[scounteren].HPM7) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM7 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM7 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM7 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM7 & CSR[scounteren].HPM7) == 1'b0) && (CSR[mcounteren].HPM7 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM7 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM7 & CSR[scounteren].HPM7) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM7 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM7 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM7 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM7 & CSR[scounteren].HPM7) == 1'b0) && (CSR[mcounteren].HPM7 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM7 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(7); + return read_hpm_counter(7); diff --git a/arch/csr/Zihpm/hpmcounter7h.yaml b/arch/csr/Zihpm/hpmcounter7h.yaml index 0fce0d221..37ee38eab 100644 --- a/arch/csr/Zihpm/hpmcounter7h.yaml +++ b/arch/csr/Zihpm/hpmcounter7h.yaml @@ -4,70 +4,72 @@ -hpmcounter7h: - long_name: User-mode Hardware Performance Counter 4, high half - address: 0xC87 - description: | - Alias for M-mode CSR `mhpmcounter7h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter7h +long_name: User-mode Hardware Performance Counter 4, high half +address: 0xC87 +description: | + Alias for M-mode CSR `mhpmcounter7h`. - Privilege mode access is controlled with `mcounteren.HPM7`, `scounteren.HPM7`, and `hcounteren.HPM7` as follows: + Privilege mode access is controlled with `mcounteren.HPM7`, `scounteren.HPM7`, and `hcounteren.HPM7` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM7`# .2+h! [.rotate]#`scounteren.HPM7`# .2+h! [.rotate]#`hcounteren.HPM7`# - 4+^.>h! `hpmcounter7h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM7`# .2+h! [.rotate]#`scounteren.HPM7`# .2+h! [.rotate]#`hcounteren.HPM7`# + 4+^.>h! `hpmcounter7h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter7h.COUNT - description: Alias of `mhpmcounter7h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter7h.COUNT + description: Alias of `mhpmcounter7h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM7 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM7 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM7 & CSR[scounteren].HPM7) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM7 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM7 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM7 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM7 & CSR[scounteren].HPM7) == 1'b0) && (CSR[mcounteren].HPM7 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM7 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM7 & CSR[scounteren].HPM7) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM7 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM7 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM7 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM7 & CSR[scounteren].HPM7) == 1'b0) && (CSR[mcounteren].HPM7 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM7 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(7)[63:32]; + return read_hpm_counter(7)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter8.yaml b/arch/csr/Zihpm/hpmcounter8.yaml index 7e96d83e4..3a1000472 100644 --- a/arch/csr/Zihpm/hpmcounter8.yaml +++ b/arch/csr/Zihpm/hpmcounter8.yaml @@ -4,100 +4,102 @@ -hpmcounter8: - long_name: User-mode Hardware Performance Counter 5 - address: 0xC08 - description: | - Alias for M-mode CSR `mhpmcounter8`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter8 +long_name: User-mode Hardware Performance Counter 5 +address: 0xC08 +description: | + Alias for M-mode CSR `mhpmcounter8`. - Privilege mode access is controlled with `mcounteren.HPM8` - <%- if ext?(:S) -%> - , `scounteren.HPM8` - <%- if ext?(:H) -%> - , and `hcounteren.HPM8` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM8` + <%- if ext?(:S) -%> + , `scounteren.HPM8` + <%- if ext?(:H) -%> + , and `hcounteren.HPM8` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM8`# .2+h! [.rotate]#`scounteren.HPM8`# .2+h! [.rotate]#`hcounteren.HPM8`# - 4+^.>h! `hpmcounter8` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM8`# .2+h! [.rotate]#`scounteren.HPM8`# .2+h! [.rotate]#`hcounteren.HPM8`# + 4+^.>h! `hpmcounter8` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM8`# .2+h! [.rotate]#`scounteren.HPM8`# - 2+^.>h! `hpmcounter8` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM8`# .2+h! [.rotate]#`scounteren.HPM8`# + 2+^.>h! `hpmcounter8` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM8`# - ^.>h! `hpmcounter8` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM8`# + ^.>h! `hpmcounter8` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter8.COUNT - description: Alias of `mhpmcounter8.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter8.COUNT + description: Alias of `mhpmcounter8.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM8 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM8 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM8 & CSR[scounteren].HPM8) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM8 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM8 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM8 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM8 & CSR[scounteren].HPM8) == 1'b0) && (CSR[mcounteren].HPM8 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM8 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM8 & CSR[scounteren].HPM8) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM8 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM8 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM8 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM8 & CSR[scounteren].HPM8) == 1'b0) && (CSR[mcounteren].HPM8 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM8 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(8); + return read_hpm_counter(8); diff --git a/arch/csr/Zihpm/hpmcounter8h.yaml b/arch/csr/Zihpm/hpmcounter8h.yaml index 8ec5e6ad8..bbba142d7 100644 --- a/arch/csr/Zihpm/hpmcounter8h.yaml +++ b/arch/csr/Zihpm/hpmcounter8h.yaml @@ -4,70 +4,72 @@ -hpmcounter8h: - long_name: User-mode Hardware Performance Counter 5, high half - address: 0xC88 - description: | - Alias for M-mode CSR `mhpmcounter8h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter8h +long_name: User-mode Hardware Performance Counter 5, high half +address: 0xC88 +description: | + Alias for M-mode CSR `mhpmcounter8h`. - Privilege mode access is controlled with `mcounteren.HPM8`, `scounteren.HPM8`, and `hcounteren.HPM8` as follows: + Privilege mode access is controlled with `mcounteren.HPM8`, `scounteren.HPM8`, and `hcounteren.HPM8` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM8`# .2+h! [.rotate]#`scounteren.HPM8`# .2+h! [.rotate]#`hcounteren.HPM8`# - 4+^.>h! `hpmcounter8h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM8`# .2+h! [.rotate]#`scounteren.HPM8`# .2+h! [.rotate]#`hcounteren.HPM8`# + 4+^.>h! `hpmcounter8h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter8h.COUNT - description: Alias of `mhpmcounter8h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter8h.COUNT + description: Alias of `mhpmcounter8h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM8 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM8 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM8 & CSR[scounteren].HPM8) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM8 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM8 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM8 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM8 & CSR[scounteren].HPM8) == 1'b0) && (CSR[mcounteren].HPM8 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM8 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM8 & CSR[scounteren].HPM8) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM8 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM8 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM8 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM8 & CSR[scounteren].HPM8) == 1'b0) && (CSR[mcounteren].HPM8 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM8 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(8)[63:32]; + return read_hpm_counter(8)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounter9.yaml b/arch/csr/Zihpm/hpmcounter9.yaml index 1ada56e25..1a62dc357 100644 --- a/arch/csr/Zihpm/hpmcounter9.yaml +++ b/arch/csr/Zihpm/hpmcounter9.yaml @@ -4,100 +4,102 @@ -hpmcounter9: - long_name: User-mode Hardware Performance Counter 6 - address: 0xC09 - description: | - Alias for M-mode CSR `mhpmcounter9`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter9 +long_name: User-mode Hardware Performance Counter 6 +address: 0xC09 +description: | + Alias for M-mode CSR `mhpmcounter9`. - Privilege mode access is controlled with `mcounteren.HPM9` - <%- if ext?(:S) -%> - , `scounteren.HPM9` - <%- if ext?(:H) -%> - , and `hcounteren.HPM9` - <%- end -%> - <%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM9` + <%- if ext?(:S) -%> + , `scounteren.HPM9` + <%- if ext?(:H) -%> + , and `hcounteren.HPM9` + <%- end -%> + <%- end -%> + as follows: - <%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM9`# .2+h! [.rotate]#`scounteren.HPM9`# .2+h! [.rotate]#`hcounteren.HPM9`# - 4+^.>h! `hpmcounter9` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM9`# .2+h! [.rotate]#`scounteren.HPM9`# .2+h! [.rotate]#`hcounteren.HPM9`# + 4+^.>h! `hpmcounter9` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM9`# .2+h! [.rotate]#`scounteren.HPM9`# - 2+^.>h! `hpmcounter9` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM9`# .2+h! [.rotate]#`scounteren.HPM9`# + 2+^.>h! `hpmcounter9` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM9`# - ^.>h! `hpmcounter9` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM9`# + ^.>h! `hpmcounter9` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter9.COUNT - description: Alias of `mhpmcounter9.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter9.COUNT + description: Alias of `mhpmcounter9.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM9 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM9 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM9 & CSR[scounteren].HPM9) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM9 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM9 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM9 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM9 & CSR[scounteren].HPM9) == 1'b0) && (CSR[mcounteren].HPM9 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM9 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM9 & CSR[scounteren].HPM9) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM9 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM9 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM9 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM9 & CSR[scounteren].HPM9) == 1'b0) && (CSR[mcounteren].HPM9 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM9 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(9); + return read_hpm_counter(9); diff --git a/arch/csr/Zihpm/hpmcounter9h.yaml b/arch/csr/Zihpm/hpmcounter9h.yaml index 99b91600a..daa0da012 100644 --- a/arch/csr/Zihpm/hpmcounter9h.yaml +++ b/arch/csr/Zihpm/hpmcounter9h.yaml @@ -4,70 +4,72 @@ -hpmcounter9h: - long_name: User-mode Hardware Performance Counter 6, high half - address: 0xC89 - description: | - Alias for M-mode CSR `mhpmcounter9h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter9h +long_name: User-mode Hardware Performance Counter 6, high half +address: 0xC89 +description: | + Alias for M-mode CSR `mhpmcounter9h`. - Privilege mode access is controlled with `mcounteren.HPM9`, `scounteren.HPM9`, and `hcounteren.HPM9` as follows: + Privilege mode access is controlled with `mcounteren.HPM9`, `scounteren.HPM9`, and `hcounteren.HPM9` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM9`# .2+h! [.rotate]#`scounteren.HPM9`# .2+h! [.rotate]#`hcounteren.HPM9`# - 4+^.>h! `hpmcounter9h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM9`# .2+h! [.rotate]#`scounteren.HPM9`# .2+h! [.rotate]#`hcounteren.HPM9`# + 4+^.>h! `hpmcounter9h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter9h.COUNT - description: Alias of `mhpmcounter9h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter9h.COUNT + description: Alias of `mhpmcounter9h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM9 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM9 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM9 & CSR[scounteren].HPM9) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM9 == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM9 == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM9 == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM9 & CSR[scounteren].HPM9) == 1'b0) && (CSR[mcounteren].HPM9 == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM9 == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM9 & CSR[scounteren].HPM9) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM9 == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM9 == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM9 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM9 & CSR[scounteren].HPM9) == 1'b0) && (CSR[mcounteren].HPM9 == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM9 == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(9)[63:32]; + return read_hpm_counter(9)[63:32]; diff --git a/arch/csr/Zihpm/hpmcounterN.layout b/arch/csr/Zihpm/hpmcounterN.layout index 32282b45f..feba9813c 100644 --- a/arch/csr/Zihpm/hpmcounterN.layout +++ b/arch/csr/Zihpm/hpmcounterN.layout @@ -2,100 +2,102 @@ <%- raise "'hpm_num' must be defined" if hpm_num.nil? -%> -hpmcounter<%= hpm_num %>: - long_name: User-mode Hardware Performance Counter <%= hpm_num - 3 %> - address: 0x<%= (0xC03 + (hpm_num - 3)).to_s(16).upcase %> - description: | - Alias for M-mode CSR `mhpmcounter<%= hpm_num %>`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter<%= hpm_num %> +long_name: User-mode Hardware Performance Counter <%= hpm_num - 3 %> +address: 0x<%= (0xC03 + (hpm_num - 3)).to_s(16).upcase %> +description: | + Alias for M-mode CSR `mhpmcounter<%= hpm_num %>`. - Privilege mode access is controlled with `mcounteren.HPM<%= hpm_num %>` - <%%- if ext?(:S) -%> - , `scounteren.HPM<%= hpm_num %>` - <%%- if ext?(:H) -%> - , and `hcounteren.HPM<%= hpm_num %>` - <%%- end -%> - <%%- end -%> - as follows: + Privilege mode access is controlled with `mcounteren.HPM<%= hpm_num %>` + <%%- if ext?(:S) -%> + , `scounteren.HPM<%= hpm_num %>` + <%%- if ext?(:H) -%> + , and `hcounteren.HPM<%= hpm_num %>` + <%%- end -%> + <%%- end -%> + as follows: - <%%- if ext?(:H) -%> - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`scounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`hcounteren.HPM<%= hpm_num %>`# - 4+^.>h! `hpmcounter<%= hpm_num %>` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + <%%- if ext?(:H) -%> + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`scounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`hcounteren.HPM<%= hpm_num %>`# + 4+^.>h! `hpmcounter<%= hpm_num %>` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - <%%- elsif ext?(:S) -%> - [%autowidth,cols="1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`scounteren.HPM<%= hpm_num %>`# - 2+^.>h! `hpmcounter<%= hpm_num %>` behavior - .^h! S-mode .^h! U-mode + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + <%%- elsif ext?(:S) -%> + [%autowidth,cols="1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`scounteren.HPM<%= hpm_num %>`# + 2+^.>h! `hpmcounter<%= hpm_num %>` behavior + .^h! S-mode .^h! U-mode - ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! read-only ! `IllegalInstruction` - ! 1 ! 1 ! read-only ! read-only - !=== - <%%- else -%> - [%autowidth,cols="1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM<%= hpm_num %>`# - ^.>h! `hpmcounter<%= hpm_num %>` behavior - .^h! U-mode + ! 0 ! - ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! read-only ! `IllegalInstruction` + ! 1 ! 1 ! read-only ! read-only + !=== + <%%- else -%> + [%autowidth,cols="1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM<%= hpm_num %>`# + ^.>h! `hpmcounter<%= hpm_num %>` behavior + .^h! U-mode - ! 0 ! `IllegalInstruction` - ! 1 ! read-only - !=== - <%%- end -%> - priv_mode: U - length: 64 - definedBy: Zihpm - fields: - COUNT: - location: 63-0 - alias: mhpmcounter<%= hpm_num %>.COUNT - description: Alias of `mhpmcounter<%= hpm_num %>.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! `IllegalInstruction` + ! 1 ! read-only + !=== + <%%- end -%> +priv_mode: U +length: 64 +definedBy: Zihpm +fields: + COUNT: + location: 63-0 + alias: mhpmcounter<%= hpm_num %>.COUNT + description: Alias of `mhpmcounter<%= hpm_num %>.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM<%= hpm_num %> & CSR[scounteren].HPM<%= hpm_num %>) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM<%= hpm_num %> == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM<%= hpm_num %> & CSR[scounteren].HPM<%= hpm_num %>) == 1'b0) && (CSR[mcounteren].HPM<%= hpm_num %> == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM<%= hpm_num %> & CSR[scounteren].HPM<%= hpm_num %>) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM<%= hpm_num %> == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM<%= hpm_num %> & CSR[scounteren].HPM<%= hpm_num %>) == 1'b0) && (CSR[mcounteren].HPM<%= hpm_num %> == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(<%= hpm_num %>); + return read_hpm_counter(<%= hpm_num %>); diff --git a/arch/csr/Zihpm/hpmcounterNh.layout b/arch/csr/Zihpm/hpmcounterNh.layout index f03372651..8a6274727 100644 --- a/arch/csr/Zihpm/hpmcounterNh.layout +++ b/arch/csr/Zihpm/hpmcounterNh.layout @@ -2,70 +2,72 @@ <%- raise "'hpm_num' must be defined" if hpm_num.nil? -%> -hpmcounter<%= hpm_num %>h: - long_name: User-mode Hardware Performance Counter <%= hpm_num - 3 %>, high half - address: 0x<%= (0xC83 + (hpm_num - 3)).to_s(16).upcase %> - description: | - Alias for M-mode CSR `mhpmcounter<%= hpm_num %>h`. +$schema: csr_schema.json# +kind: csr +name: hpmcounter<%= hpm_num %>h +long_name: User-mode Hardware Performance Counter <%= hpm_num - 3 %>, high half +address: 0x<%= (0xC83 + (hpm_num - 3)).to_s(16).upcase %> +description: | + Alias for M-mode CSR `mhpmcounter<%= hpm_num %>h`. - Privilege mode access is controlled with `mcounteren.HPM<%= hpm_num %>`, `scounteren.HPM<%= hpm_num %>`, and `hcounteren.HPM<%= hpm_num %>` as follows: + Privilege mode access is controlled with `mcounteren.HPM<%= hpm_num %>`, `scounteren.HPM<%= hpm_num %>`, and `hcounteren.HPM<%= hpm_num %>` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`scounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`hcounteren.HPM<%= hpm_num %>`# - 4+^.>h! `hpmcounter<%= hpm_num %>h` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`scounteren.HPM<%= hpm_num %>`# .2+h! [.rotate]#`hcounteren.HPM<%= hpm_num %>`# + 4+^.>h! `hpmcounter<%= hpm_num %>h` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Sscofpmf - fields: - COUNT: - location: 63-0 - alias: mhpmcounter<%= hpm_num %>h.COUNT - description: Alias of `mhpmcounter<%= hpm_num %>h.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Sscofpmf +fields: + COUNT: + location: 63-0 + alias: mhpmcounter<%= hpm_num %>h.COUNT + description: Alias of `mhpmcounter<%= hpm_num %>h.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].HPM<%= hpm_num %> & CSR[scounteren].HPM<%= hpm_num %>) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].HPM<%= hpm_num %> == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].HPM<%= hpm_num %> & CSR[scounteren].HPM<%= hpm_num %>) == 1'b0) && (CSR[mcounteren].HPM<%= hpm_num %> == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].HPM<%= hpm_num %> & CSR[scounteren].HPM<%= hpm_num %>) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].HPM<%= hpm_num %> == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].HPM<%= hpm_num %> & CSR[scounteren].HPM<%= hpm_num %>) == 1'b0) && (CSR[mcounteren].HPM<%= hpm_num %> == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].HPM<%= hpm_num %> == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_hpm_counter(<%= hpm_num %>)[63:32]; + return read_hpm_counter(<%= hpm_num %>)[63:32]; diff --git a/arch/csr/Zihpm/mhpmcounter10.yaml b/arch/csr/Zihpm/mhpmcounter10.yaml index 124fd0726..abcf005ae 100644 --- a/arch/csr/Zihpm/mhpmcounter10.yaml +++ b/arch/csr/Zihpm/mhpmcounter10.yaml @@ -4,47 +4,49 @@ -mhpmcounter10: - long_name: Machine Hardware Performance Counter 10 - address: 0xB0A - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[10] == true"] - -- - Performance counter for event selected in `mhpmevent10.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM10` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM10`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent10.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent10.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent10..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent10.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent10.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent10.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent10.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent10.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent10.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[10] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[10]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[10]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[10]) { - return read_hpm_counter(10); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter10 +long_name: Machine Hardware Performance Counter 10 +address: 0xB0A +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[10] == true"] + -- + Performance counter for event selected in `mhpmevent10.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM10` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM10`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent10.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent10.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent10..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent10.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent10.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent10.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent10.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent10.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent10.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[10] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[10]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[10]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[10]) { + return read_hpm_counter(10); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter10h.yaml b/arch/csr/Zihpm/mhpmcounter10h.yaml index 595497b28..d0921b108 100644 --- a/arch/csr/Zihpm/mhpmcounter10h.yaml +++ b/arch/csr/Zihpm/mhpmcounter10h.yaml @@ -4,26 +4,28 @@ -mhpmcounter10h: - long_name: Machine Hardware Performance Counter 10, Upper half - address: 0xB8A - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter10. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT10[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[10]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[10]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[10]) { - return read_hpm_counter(10)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter10h +long_name: Machine Hardware Performance Counter 10, Upper half +address: 0xB8A +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter10. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT10[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[10]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[10]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[10]) { + return read_hpm_counter(10)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter11.yaml b/arch/csr/Zihpm/mhpmcounter11.yaml index 82519cd0b..311fc0cf1 100644 --- a/arch/csr/Zihpm/mhpmcounter11.yaml +++ b/arch/csr/Zihpm/mhpmcounter11.yaml @@ -4,47 +4,49 @@ -mhpmcounter11: - long_name: Machine Hardware Performance Counter 11 - address: 0xB0B - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[11] == true"] - -- - Performance counter for event selected in `mhpmevent11.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM11` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM11`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent11.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent11.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent11..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent11.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent11.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent11.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent11.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent11.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent11.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[11] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[11]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[11]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[11]) { - return read_hpm_counter(11); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter11 +long_name: Machine Hardware Performance Counter 11 +address: 0xB0B +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[11] == true"] + -- + Performance counter for event selected in `mhpmevent11.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM11` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM11`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent11.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent11.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent11..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent11.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent11.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent11.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent11.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent11.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent11.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[11] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[11]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[11]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[11]) { + return read_hpm_counter(11); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter11h.yaml b/arch/csr/Zihpm/mhpmcounter11h.yaml index 8cc262a35..480175167 100644 --- a/arch/csr/Zihpm/mhpmcounter11h.yaml +++ b/arch/csr/Zihpm/mhpmcounter11h.yaml @@ -4,26 +4,28 @@ -mhpmcounter11h: - long_name: Machine Hardware Performance Counter 11, Upper half - address: 0xB8B - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter11. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT11[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[11]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[11]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[11]) { - return read_hpm_counter(11)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter11h +long_name: Machine Hardware Performance Counter 11, Upper half +address: 0xB8B +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter11. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT11[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[11]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[11]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[11]) { + return read_hpm_counter(11)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter12.yaml b/arch/csr/Zihpm/mhpmcounter12.yaml index ee241a5a2..fb1f3e895 100644 --- a/arch/csr/Zihpm/mhpmcounter12.yaml +++ b/arch/csr/Zihpm/mhpmcounter12.yaml @@ -4,47 +4,49 @@ -mhpmcounter12: - long_name: Machine Hardware Performance Counter 12 - address: 0xB0C - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[12] == true"] - -- - Performance counter for event selected in `mhpmevent12.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM12` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM12`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent12.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent12.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent12..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent12.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent12.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent12.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent12.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent12.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent12.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[12] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[12]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[12]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[12]) { - return read_hpm_counter(12); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter12 +long_name: Machine Hardware Performance Counter 12 +address: 0xB0C +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[12] == true"] + -- + Performance counter for event selected in `mhpmevent12.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM12` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM12`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent12.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent12.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent12..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent12.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent12.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent12.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent12.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent12.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent12.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[12] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[12]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[12]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[12]) { + return read_hpm_counter(12); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter12h.yaml b/arch/csr/Zihpm/mhpmcounter12h.yaml index ec2d0af69..9b376187f 100644 --- a/arch/csr/Zihpm/mhpmcounter12h.yaml +++ b/arch/csr/Zihpm/mhpmcounter12h.yaml @@ -4,26 +4,28 @@ -mhpmcounter12h: - long_name: Machine Hardware Performance Counter 12, Upper half - address: 0xB8C - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter12. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT12[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[12]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[12]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[12]) { - return read_hpm_counter(12)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter12h +long_name: Machine Hardware Performance Counter 12, Upper half +address: 0xB8C +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter12. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT12[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[12]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[12]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[12]) { + return read_hpm_counter(12)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter13.yaml b/arch/csr/Zihpm/mhpmcounter13.yaml index c50b9f88f..5ac700007 100644 --- a/arch/csr/Zihpm/mhpmcounter13.yaml +++ b/arch/csr/Zihpm/mhpmcounter13.yaml @@ -4,47 +4,49 @@ -mhpmcounter13: - long_name: Machine Hardware Performance Counter 13 - address: 0xB0D - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[13] == true"] - -- - Performance counter for event selected in `mhpmevent13.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM13` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM13`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent13.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent13.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent13..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent13.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent13.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent13.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent13.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent13.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent13.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[13] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[13]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[13]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[13]) { - return read_hpm_counter(13); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter13 +long_name: Machine Hardware Performance Counter 13 +address: 0xB0D +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[13] == true"] + -- + Performance counter for event selected in `mhpmevent13.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM13` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM13`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent13.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent13.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent13..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent13.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent13.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent13.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent13.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent13.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent13.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[13] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[13]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[13]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[13]) { + return read_hpm_counter(13); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter13h.yaml b/arch/csr/Zihpm/mhpmcounter13h.yaml index 5183d8a2d..2fa48f8d3 100644 --- a/arch/csr/Zihpm/mhpmcounter13h.yaml +++ b/arch/csr/Zihpm/mhpmcounter13h.yaml @@ -4,26 +4,28 @@ -mhpmcounter13h: - long_name: Machine Hardware Performance Counter 13, Upper half - address: 0xB8D - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter13. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT13[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[13]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[13]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[13]) { - return read_hpm_counter(13)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter13h +long_name: Machine Hardware Performance Counter 13, Upper half +address: 0xB8D +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter13. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT13[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[13]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[13]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[13]) { + return read_hpm_counter(13)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter14.yaml b/arch/csr/Zihpm/mhpmcounter14.yaml index ae91a6329..f9da216b0 100644 --- a/arch/csr/Zihpm/mhpmcounter14.yaml +++ b/arch/csr/Zihpm/mhpmcounter14.yaml @@ -4,47 +4,49 @@ -mhpmcounter14: - long_name: Machine Hardware Performance Counter 14 - address: 0xB0E - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[14] == true"] - -- - Performance counter for event selected in `mhpmevent14.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM14` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM14`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent14.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent14.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent14..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent14.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent14.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent14.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent14.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent14.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent14.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[14] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[14]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[14]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[14]) { - return read_hpm_counter(14); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter14 +long_name: Machine Hardware Performance Counter 14 +address: 0xB0E +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[14] == true"] + -- + Performance counter for event selected in `mhpmevent14.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM14` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM14`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent14.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent14.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent14..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent14.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent14.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent14.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent14.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent14.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent14.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[14] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[14]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[14]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[14]) { + return read_hpm_counter(14); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter14h.yaml b/arch/csr/Zihpm/mhpmcounter14h.yaml index 21ab86239..02a78cf6f 100644 --- a/arch/csr/Zihpm/mhpmcounter14h.yaml +++ b/arch/csr/Zihpm/mhpmcounter14h.yaml @@ -4,26 +4,28 @@ -mhpmcounter14h: - long_name: Machine Hardware Performance Counter 14, Upper half - address: 0xB8E - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter14. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT14[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[14]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[14]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[14]) { - return read_hpm_counter(14)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter14h +long_name: Machine Hardware Performance Counter 14, Upper half +address: 0xB8E +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter14. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT14[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[14]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[14]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[14]) { + return read_hpm_counter(14)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter15.yaml b/arch/csr/Zihpm/mhpmcounter15.yaml index 7453299d1..fa067b80e 100644 --- a/arch/csr/Zihpm/mhpmcounter15.yaml +++ b/arch/csr/Zihpm/mhpmcounter15.yaml @@ -4,47 +4,49 @@ -mhpmcounter15: - long_name: Machine Hardware Performance Counter 15 - address: 0xB0F - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[15] == true"] - -- - Performance counter for event selected in `mhpmevent15.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM15` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM15`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent15.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent15.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent15..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent15.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent15.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent15.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent15.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent15.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent15.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[15] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[15]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[15]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[15]) { - return read_hpm_counter(15); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter15 +long_name: Machine Hardware Performance Counter 15 +address: 0xB0F +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[15] == true"] + -- + Performance counter for event selected in `mhpmevent15.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM15` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM15`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent15.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent15.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent15..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent15.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent15.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent15.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent15.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent15.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent15.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[15] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[15]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[15]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[15]) { + return read_hpm_counter(15); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter15h.yaml b/arch/csr/Zihpm/mhpmcounter15h.yaml index a398cd893..6c2694f66 100644 --- a/arch/csr/Zihpm/mhpmcounter15h.yaml +++ b/arch/csr/Zihpm/mhpmcounter15h.yaml @@ -4,26 +4,28 @@ -mhpmcounter15h: - long_name: Machine Hardware Performance Counter 15, Upper half - address: 0xB8F - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter15. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT15[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[15]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[15]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[15]) { - return read_hpm_counter(15)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter15h +long_name: Machine Hardware Performance Counter 15, Upper half +address: 0xB8F +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter15. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT15[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[15]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[15]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[15]) { + return read_hpm_counter(15)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter16.yaml b/arch/csr/Zihpm/mhpmcounter16.yaml index 9ecb490af..3c0a9f6eb 100644 --- a/arch/csr/Zihpm/mhpmcounter16.yaml +++ b/arch/csr/Zihpm/mhpmcounter16.yaml @@ -4,47 +4,49 @@ -mhpmcounter16: - long_name: Machine Hardware Performance Counter 16 - address: 0xB10 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[16] == true"] - -- - Performance counter for event selected in `mhpmevent16.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM16` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM16`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent16.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent16.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent16..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent16.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent16.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent16.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent16.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent16.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent16.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[16] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[16]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[16]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[16]) { - return read_hpm_counter(16); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter16 +long_name: Machine Hardware Performance Counter 16 +address: 0xB10 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[16] == true"] + -- + Performance counter for event selected in `mhpmevent16.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM16` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM16`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent16.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent16.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent16..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent16.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent16.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent16.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent16.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent16.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent16.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[16] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[16]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[16]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[16]) { + return read_hpm_counter(16); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter16h.yaml b/arch/csr/Zihpm/mhpmcounter16h.yaml index 6839ff625..2efc26bc1 100644 --- a/arch/csr/Zihpm/mhpmcounter16h.yaml +++ b/arch/csr/Zihpm/mhpmcounter16h.yaml @@ -4,26 +4,28 @@ -mhpmcounter16h: - long_name: Machine Hardware Performance Counter 16, Upper half - address: 0xB90 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter16. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT16[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[16]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[16]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[16]) { - return read_hpm_counter(16)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter16h +long_name: Machine Hardware Performance Counter 16, Upper half +address: 0xB90 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter16. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT16[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[16]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[16]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[16]) { + return read_hpm_counter(16)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter17.yaml b/arch/csr/Zihpm/mhpmcounter17.yaml index dddc55116..a053f43f7 100644 --- a/arch/csr/Zihpm/mhpmcounter17.yaml +++ b/arch/csr/Zihpm/mhpmcounter17.yaml @@ -4,47 +4,49 @@ -mhpmcounter17: - long_name: Machine Hardware Performance Counter 17 - address: 0xB11 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[17] == true"] - -- - Performance counter for event selected in `mhpmevent17.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM17` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM17`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent17.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent17.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent17..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent17.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent17.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent17.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent17.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent17.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent17.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[17] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[17]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[17]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[17]) { - return read_hpm_counter(17); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter17 +long_name: Machine Hardware Performance Counter 17 +address: 0xB11 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[17] == true"] + -- + Performance counter for event selected in `mhpmevent17.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM17` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM17`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent17.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent17.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent17..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent17.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent17.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent17.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent17.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent17.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent17.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[17] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[17]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[17]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[17]) { + return read_hpm_counter(17); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter17h.yaml b/arch/csr/Zihpm/mhpmcounter17h.yaml index 1dcc9db27..6983f5a66 100644 --- a/arch/csr/Zihpm/mhpmcounter17h.yaml +++ b/arch/csr/Zihpm/mhpmcounter17h.yaml @@ -4,26 +4,28 @@ -mhpmcounter17h: - long_name: Machine Hardware Performance Counter 17, Upper half - address: 0xB91 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter17. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT17[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[17]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[17]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[17]) { - return read_hpm_counter(17)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter17h +long_name: Machine Hardware Performance Counter 17, Upper half +address: 0xB91 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter17. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT17[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[17]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[17]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[17]) { + return read_hpm_counter(17)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter18.yaml b/arch/csr/Zihpm/mhpmcounter18.yaml index 4cc3e014b..8487fd364 100644 --- a/arch/csr/Zihpm/mhpmcounter18.yaml +++ b/arch/csr/Zihpm/mhpmcounter18.yaml @@ -4,47 +4,49 @@ -mhpmcounter18: - long_name: Machine Hardware Performance Counter 18 - address: 0xB12 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[18] == true"] - -- - Performance counter for event selected in `mhpmevent18.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM18` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM18`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent18.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent18.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent18..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent18.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent18.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent18.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent18.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent18.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent18.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[18] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[18]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[18]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[18]) { - return read_hpm_counter(18); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter18 +long_name: Machine Hardware Performance Counter 18 +address: 0xB12 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[18] == true"] + -- + Performance counter for event selected in `mhpmevent18.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM18` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM18`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent18.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent18.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent18..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent18.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent18.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent18.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent18.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent18.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent18.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[18] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[18]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[18]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[18]) { + return read_hpm_counter(18); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter18h.yaml b/arch/csr/Zihpm/mhpmcounter18h.yaml index 2a447e930..2c55efb86 100644 --- a/arch/csr/Zihpm/mhpmcounter18h.yaml +++ b/arch/csr/Zihpm/mhpmcounter18h.yaml @@ -4,26 +4,28 @@ -mhpmcounter18h: - long_name: Machine Hardware Performance Counter 18, Upper half - address: 0xB92 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter18. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT18[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[18]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[18]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[18]) { - return read_hpm_counter(18)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter18h +long_name: Machine Hardware Performance Counter 18, Upper half +address: 0xB92 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter18. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT18[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[18]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[18]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[18]) { + return read_hpm_counter(18)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter19.yaml b/arch/csr/Zihpm/mhpmcounter19.yaml index ba1c07d37..df0b9be79 100644 --- a/arch/csr/Zihpm/mhpmcounter19.yaml +++ b/arch/csr/Zihpm/mhpmcounter19.yaml @@ -4,47 +4,49 @@ -mhpmcounter19: - long_name: Machine Hardware Performance Counter 19 - address: 0xB13 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[19] == true"] - -- - Performance counter for event selected in `mhpmevent19.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM19` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM19`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent19.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent19.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent19..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent19.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent19.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent19.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent19.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent19.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent19.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[19] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[19]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[19]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[19]) { - return read_hpm_counter(19); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter19 +long_name: Machine Hardware Performance Counter 19 +address: 0xB13 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[19] == true"] + -- + Performance counter for event selected in `mhpmevent19.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM19` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM19`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent19.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent19.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent19..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent19.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent19.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent19.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent19.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent19.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent19.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[19] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[19]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[19]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[19]) { + return read_hpm_counter(19); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter19h.yaml b/arch/csr/Zihpm/mhpmcounter19h.yaml index ea3dfdf35..6810df997 100644 --- a/arch/csr/Zihpm/mhpmcounter19h.yaml +++ b/arch/csr/Zihpm/mhpmcounter19h.yaml @@ -4,26 +4,28 @@ -mhpmcounter19h: - long_name: Machine Hardware Performance Counter 19, Upper half - address: 0xB93 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter19. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT19[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[19]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[19]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[19]) { - return read_hpm_counter(19)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter19h +long_name: Machine Hardware Performance Counter 19, Upper half +address: 0xB93 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter19. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT19[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[19]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[19]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[19]) { + return read_hpm_counter(19)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter20.yaml b/arch/csr/Zihpm/mhpmcounter20.yaml index c8e33e9b4..c902cf875 100644 --- a/arch/csr/Zihpm/mhpmcounter20.yaml +++ b/arch/csr/Zihpm/mhpmcounter20.yaml @@ -4,47 +4,49 @@ -mhpmcounter20: - long_name: Machine Hardware Performance Counter 20 - address: 0xB14 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[20] == true"] - -- - Performance counter for event selected in `mhpmevent20.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM20` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM20`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent20.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent20.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent20..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent20.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent20.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent20.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent20.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent20.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent20.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[20] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[20]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[20]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[20]) { - return read_hpm_counter(20); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter20 +long_name: Machine Hardware Performance Counter 20 +address: 0xB14 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[20] == true"] + -- + Performance counter for event selected in `mhpmevent20.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM20` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM20`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent20.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent20.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent20..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent20.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent20.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent20.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent20.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent20.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent20.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[20] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[20]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[20]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[20]) { + return read_hpm_counter(20); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter20h.yaml b/arch/csr/Zihpm/mhpmcounter20h.yaml index 9754fff36..00373df91 100644 --- a/arch/csr/Zihpm/mhpmcounter20h.yaml +++ b/arch/csr/Zihpm/mhpmcounter20h.yaml @@ -4,26 +4,28 @@ -mhpmcounter20h: - long_name: Machine Hardware Performance Counter 20, Upper half - address: 0xB94 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter20. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT20[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[20]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[20]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[20]) { - return read_hpm_counter(20)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter20h +long_name: Machine Hardware Performance Counter 20, Upper half +address: 0xB94 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter20. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT20[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[20]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[20]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[20]) { + return read_hpm_counter(20)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter21.yaml b/arch/csr/Zihpm/mhpmcounter21.yaml index f8c4bb73e..961203af3 100644 --- a/arch/csr/Zihpm/mhpmcounter21.yaml +++ b/arch/csr/Zihpm/mhpmcounter21.yaml @@ -4,47 +4,49 @@ -mhpmcounter21: - long_name: Machine Hardware Performance Counter 21 - address: 0xB15 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[21] == true"] - -- - Performance counter for event selected in `mhpmevent21.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM21` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM21`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent21.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent21.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent21..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent21.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent21.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent21.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent21.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent21.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent21.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[21] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[21]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[21]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[21]) { - return read_hpm_counter(21); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter21 +long_name: Machine Hardware Performance Counter 21 +address: 0xB15 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[21] == true"] + -- + Performance counter for event selected in `mhpmevent21.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM21` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM21`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent21.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent21.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent21..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent21.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent21.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent21.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent21.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent21.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent21.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[21] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[21]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[21]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[21]) { + return read_hpm_counter(21); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter21h.yaml b/arch/csr/Zihpm/mhpmcounter21h.yaml index 4daf18081..e1759442d 100644 --- a/arch/csr/Zihpm/mhpmcounter21h.yaml +++ b/arch/csr/Zihpm/mhpmcounter21h.yaml @@ -4,26 +4,28 @@ -mhpmcounter21h: - long_name: Machine Hardware Performance Counter 21, Upper half - address: 0xB95 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter21. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT21[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[21]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[21]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[21]) { - return read_hpm_counter(21)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter21h +long_name: Machine Hardware Performance Counter 21, Upper half +address: 0xB95 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter21. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT21[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[21]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[21]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[21]) { + return read_hpm_counter(21)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter22.yaml b/arch/csr/Zihpm/mhpmcounter22.yaml index aec2c85e6..1f1df6c96 100644 --- a/arch/csr/Zihpm/mhpmcounter22.yaml +++ b/arch/csr/Zihpm/mhpmcounter22.yaml @@ -4,47 +4,49 @@ -mhpmcounter22: - long_name: Machine Hardware Performance Counter 22 - address: 0xB16 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[22] == true"] - -- - Performance counter for event selected in `mhpmevent22.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM22` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM22`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent22.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent22.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent22..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent22.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent22.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent22.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent22.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent22.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent22.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[22] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[22]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[22]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[22]) { - return read_hpm_counter(22); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter22 +long_name: Machine Hardware Performance Counter 22 +address: 0xB16 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[22] == true"] + -- + Performance counter for event selected in `mhpmevent22.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM22` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM22`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent22.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent22.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent22..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent22.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent22.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent22.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent22.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent22.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent22.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[22] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[22]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[22]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[22]) { + return read_hpm_counter(22); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter22h.yaml b/arch/csr/Zihpm/mhpmcounter22h.yaml index 9a7e3f613..de6284ce5 100644 --- a/arch/csr/Zihpm/mhpmcounter22h.yaml +++ b/arch/csr/Zihpm/mhpmcounter22h.yaml @@ -4,26 +4,28 @@ -mhpmcounter22h: - long_name: Machine Hardware Performance Counter 22, Upper half - address: 0xB96 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter22. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT22[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[22]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[22]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[22]) { - return read_hpm_counter(22)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter22h +long_name: Machine Hardware Performance Counter 22, Upper half +address: 0xB96 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter22. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT22[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[22]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[22]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[22]) { + return read_hpm_counter(22)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter23.yaml b/arch/csr/Zihpm/mhpmcounter23.yaml index e00604fbe..83c25f79f 100644 --- a/arch/csr/Zihpm/mhpmcounter23.yaml +++ b/arch/csr/Zihpm/mhpmcounter23.yaml @@ -4,47 +4,49 @@ -mhpmcounter23: - long_name: Machine Hardware Performance Counter 23 - address: 0xB17 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[23] == true"] - -- - Performance counter for event selected in `mhpmevent23.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM23` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM23`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent23.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent23.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent23..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent23.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent23.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent23.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent23.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent23.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent23.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[23] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[23]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[23]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[23]) { - return read_hpm_counter(23); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter23 +long_name: Machine Hardware Performance Counter 23 +address: 0xB17 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[23] == true"] + -- + Performance counter for event selected in `mhpmevent23.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM23` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM23`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent23.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent23.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent23..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent23.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent23.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent23.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent23.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent23.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent23.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[23] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[23]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[23]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[23]) { + return read_hpm_counter(23); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter23h.yaml b/arch/csr/Zihpm/mhpmcounter23h.yaml index 3b38449a7..5208fa471 100644 --- a/arch/csr/Zihpm/mhpmcounter23h.yaml +++ b/arch/csr/Zihpm/mhpmcounter23h.yaml @@ -4,26 +4,28 @@ -mhpmcounter23h: - long_name: Machine Hardware Performance Counter 23, Upper half - address: 0xB97 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter23. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT23[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[23]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[23]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[23]) { - return read_hpm_counter(23)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter23h +long_name: Machine Hardware Performance Counter 23, Upper half +address: 0xB97 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter23. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT23[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[23]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[23]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[23]) { + return read_hpm_counter(23)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter24.yaml b/arch/csr/Zihpm/mhpmcounter24.yaml index 6e605ed9f..c68626718 100644 --- a/arch/csr/Zihpm/mhpmcounter24.yaml +++ b/arch/csr/Zihpm/mhpmcounter24.yaml @@ -4,47 +4,49 @@ -mhpmcounter24: - long_name: Machine Hardware Performance Counter 24 - address: 0xB18 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[24] == true"] - -- - Performance counter for event selected in `mhpmevent24.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM24` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM24`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent24.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent24.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent24..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent24.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent24.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent24.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent24.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent24.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent24.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[24] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[24]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[24]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[24]) { - return read_hpm_counter(24); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter24 +long_name: Machine Hardware Performance Counter 24 +address: 0xB18 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[24] == true"] + -- + Performance counter for event selected in `mhpmevent24.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM24` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM24`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent24.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent24.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent24..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent24.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent24.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent24.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent24.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent24.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent24.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[24] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[24]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[24]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[24]) { + return read_hpm_counter(24); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter24h.yaml b/arch/csr/Zihpm/mhpmcounter24h.yaml index c3ba869d9..76808b2a6 100644 --- a/arch/csr/Zihpm/mhpmcounter24h.yaml +++ b/arch/csr/Zihpm/mhpmcounter24h.yaml @@ -4,26 +4,28 @@ -mhpmcounter24h: - long_name: Machine Hardware Performance Counter 24, Upper half - address: 0xB98 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter24. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT24[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[24]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[24]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[24]) { - return read_hpm_counter(24)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter24h +long_name: Machine Hardware Performance Counter 24, Upper half +address: 0xB98 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter24. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT24[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[24]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[24]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[24]) { + return read_hpm_counter(24)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter25.yaml b/arch/csr/Zihpm/mhpmcounter25.yaml index a7ebe7326..dca9e4028 100644 --- a/arch/csr/Zihpm/mhpmcounter25.yaml +++ b/arch/csr/Zihpm/mhpmcounter25.yaml @@ -4,47 +4,49 @@ -mhpmcounter25: - long_name: Machine Hardware Performance Counter 25 - address: 0xB19 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[25] == true"] - -- - Performance counter for event selected in `mhpmevent25.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM25` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM25`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent25.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent25.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent25..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent25.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent25.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent25.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent25.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent25.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent25.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[25] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[25]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[25]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[25]) { - return read_hpm_counter(25); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter25 +long_name: Machine Hardware Performance Counter 25 +address: 0xB19 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[25] == true"] + -- + Performance counter for event selected in `mhpmevent25.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM25` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM25`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent25.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent25.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent25..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent25.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent25.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent25.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent25.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent25.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent25.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[25] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[25]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[25]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[25]) { + return read_hpm_counter(25); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter25h.yaml b/arch/csr/Zihpm/mhpmcounter25h.yaml index 8eb4ce742..1829aca09 100644 --- a/arch/csr/Zihpm/mhpmcounter25h.yaml +++ b/arch/csr/Zihpm/mhpmcounter25h.yaml @@ -4,26 +4,28 @@ -mhpmcounter25h: - long_name: Machine Hardware Performance Counter 25, Upper half - address: 0xB99 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter25. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT25[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[25]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[25]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[25]) { - return read_hpm_counter(25)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter25h +long_name: Machine Hardware Performance Counter 25, Upper half +address: 0xB99 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter25. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT25[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[25]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[25]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[25]) { + return read_hpm_counter(25)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter26.yaml b/arch/csr/Zihpm/mhpmcounter26.yaml index a61927f9a..0f70f1721 100644 --- a/arch/csr/Zihpm/mhpmcounter26.yaml +++ b/arch/csr/Zihpm/mhpmcounter26.yaml @@ -4,47 +4,49 @@ -mhpmcounter26: - long_name: Machine Hardware Performance Counter 26 - address: 0xB1A - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[26] == true"] - -- - Performance counter for event selected in `mhpmevent26.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM26` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM26`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent26.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent26.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent26..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent26.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent26.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent26.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent26.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent26.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent26.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[26] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[26]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[26]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[26]) { - return read_hpm_counter(26); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter26 +long_name: Machine Hardware Performance Counter 26 +address: 0xB1A +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[26] == true"] + -- + Performance counter for event selected in `mhpmevent26.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM26` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM26`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent26.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent26.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent26..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent26.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent26.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent26.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent26.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent26.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent26.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[26] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[26]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[26]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[26]) { + return read_hpm_counter(26); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter26h.yaml b/arch/csr/Zihpm/mhpmcounter26h.yaml index a1acb9156..3ea26055d 100644 --- a/arch/csr/Zihpm/mhpmcounter26h.yaml +++ b/arch/csr/Zihpm/mhpmcounter26h.yaml @@ -4,26 +4,28 @@ -mhpmcounter26h: - long_name: Machine Hardware Performance Counter 26, Upper half - address: 0xB9A - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter26. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT26[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[26]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[26]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[26]) { - return read_hpm_counter(26)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter26h +long_name: Machine Hardware Performance Counter 26, Upper half +address: 0xB9A +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter26. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT26[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[26]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[26]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[26]) { + return read_hpm_counter(26)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter27.yaml b/arch/csr/Zihpm/mhpmcounter27.yaml index 3566b567f..2682ce374 100644 --- a/arch/csr/Zihpm/mhpmcounter27.yaml +++ b/arch/csr/Zihpm/mhpmcounter27.yaml @@ -4,47 +4,49 @@ -mhpmcounter27: - long_name: Machine Hardware Performance Counter 27 - address: 0xB1B - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[27] == true"] - -- - Performance counter for event selected in `mhpmevent27.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM27` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM27`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent27.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent27.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent27..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent27.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent27.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent27.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent27.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent27.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent27.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[27] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[27]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[27]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[27]) { - return read_hpm_counter(27); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter27 +long_name: Machine Hardware Performance Counter 27 +address: 0xB1B +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[27] == true"] + -- + Performance counter for event selected in `mhpmevent27.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM27` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM27`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent27.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent27.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent27..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent27.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent27.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent27.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent27.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent27.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent27.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[27] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[27]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[27]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[27]) { + return read_hpm_counter(27); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter27h.yaml b/arch/csr/Zihpm/mhpmcounter27h.yaml index f62c6c9ba..750305e5a 100644 --- a/arch/csr/Zihpm/mhpmcounter27h.yaml +++ b/arch/csr/Zihpm/mhpmcounter27h.yaml @@ -4,26 +4,28 @@ -mhpmcounter27h: - long_name: Machine Hardware Performance Counter 27, Upper half - address: 0xB9B - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter27. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT27[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[27]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[27]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[27]) { - return read_hpm_counter(27)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter27h +long_name: Machine Hardware Performance Counter 27, Upper half +address: 0xB9B +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter27. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT27[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[27]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[27]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[27]) { + return read_hpm_counter(27)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter28.yaml b/arch/csr/Zihpm/mhpmcounter28.yaml index 368d0ac85..a1c4fbb25 100644 --- a/arch/csr/Zihpm/mhpmcounter28.yaml +++ b/arch/csr/Zihpm/mhpmcounter28.yaml @@ -4,47 +4,49 @@ -mhpmcounter28: - long_name: Machine Hardware Performance Counter 28 - address: 0xB1C - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[28] == true"] - -- - Performance counter for event selected in `mhpmevent28.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM28` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM28`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent28.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent28.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent28..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent28.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent28.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent28.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent28.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent28.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent28.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[28] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[28]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[28]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[28]) { - return read_hpm_counter(28); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter28 +long_name: Machine Hardware Performance Counter 28 +address: 0xB1C +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[28] == true"] + -- + Performance counter for event selected in `mhpmevent28.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM28` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM28`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent28.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent28.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent28..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent28.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent28.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent28.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent28.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent28.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent28.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[28] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[28]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[28]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[28]) { + return read_hpm_counter(28); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter28h.yaml b/arch/csr/Zihpm/mhpmcounter28h.yaml index 0e08592a5..d210f2a60 100644 --- a/arch/csr/Zihpm/mhpmcounter28h.yaml +++ b/arch/csr/Zihpm/mhpmcounter28h.yaml @@ -4,26 +4,28 @@ -mhpmcounter28h: - long_name: Machine Hardware Performance Counter 28, Upper half - address: 0xB9C - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter28. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT28[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[28]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[28]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[28]) { - return read_hpm_counter(28)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter28h +long_name: Machine Hardware Performance Counter 28, Upper half +address: 0xB9C +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter28. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT28[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[28]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[28]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[28]) { + return read_hpm_counter(28)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter29.yaml b/arch/csr/Zihpm/mhpmcounter29.yaml index db50e17f2..6127a0c55 100644 --- a/arch/csr/Zihpm/mhpmcounter29.yaml +++ b/arch/csr/Zihpm/mhpmcounter29.yaml @@ -4,47 +4,49 @@ -mhpmcounter29: - long_name: Machine Hardware Performance Counter 29 - address: 0xB1D - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[29] == true"] - -- - Performance counter for event selected in `mhpmevent29.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM29` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM29`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent29.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent29.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent29..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent29.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent29.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent29.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent29.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent29.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent29.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[29] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[29]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[29]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[29]) { - return read_hpm_counter(29); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter29 +long_name: Machine Hardware Performance Counter 29 +address: 0xB1D +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[29] == true"] + -- + Performance counter for event selected in `mhpmevent29.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM29` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM29`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent29.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent29.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent29..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent29.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent29.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent29.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent29.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent29.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent29.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[29] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[29]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[29]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[29]) { + return read_hpm_counter(29); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter29h.yaml b/arch/csr/Zihpm/mhpmcounter29h.yaml index b68805332..5f493f590 100644 --- a/arch/csr/Zihpm/mhpmcounter29h.yaml +++ b/arch/csr/Zihpm/mhpmcounter29h.yaml @@ -4,26 +4,28 @@ -mhpmcounter29h: - long_name: Machine Hardware Performance Counter 29, Upper half - address: 0xB9D - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter29. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT29[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[29]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[29]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[29]) { - return read_hpm_counter(29)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter29h +long_name: Machine Hardware Performance Counter 29, Upper half +address: 0xB9D +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter29. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT29[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[29]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[29]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[29]) { + return read_hpm_counter(29)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter3.yaml b/arch/csr/Zihpm/mhpmcounter3.yaml index a5eeaace7..61729e21a 100644 --- a/arch/csr/Zihpm/mhpmcounter3.yaml +++ b/arch/csr/Zihpm/mhpmcounter3.yaml @@ -4,47 +4,49 @@ -mhpmcounter3: - long_name: Machine Hardware Performance Counter 3 - address: 0xB03 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[3] == true"] - -- - Performance counter for event selected in `mhpmevent3.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM3` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM3`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent3.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent3.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent3..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent3.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent3.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent3.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent3.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent3.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent3.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[3] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[3]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[3]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[3]) { - return read_hpm_counter(3); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter3 +long_name: Machine Hardware Performance Counter 3 +address: 0xB03 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[3] == true"] + -- + Performance counter for event selected in `mhpmevent3.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM3` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM3`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent3.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent3.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent3..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent3.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent3.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent3.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent3.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent3.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent3.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[3] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[3]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[3]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[3]) { + return read_hpm_counter(3); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter30.yaml b/arch/csr/Zihpm/mhpmcounter30.yaml index b9fd4f1a8..a4ab437be 100644 --- a/arch/csr/Zihpm/mhpmcounter30.yaml +++ b/arch/csr/Zihpm/mhpmcounter30.yaml @@ -4,47 +4,49 @@ -mhpmcounter30: - long_name: Machine Hardware Performance Counter 30 - address: 0xB1E - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[30] == true"] - -- - Performance counter for event selected in `mhpmevent30.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM30` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM30`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent30.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent30.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent30..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent30.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent30.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent30.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent30.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent30.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent30.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[30] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[30]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[30]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[30]) { - return read_hpm_counter(30); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter30 +long_name: Machine Hardware Performance Counter 30 +address: 0xB1E +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[30] == true"] + -- + Performance counter for event selected in `mhpmevent30.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM30` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM30`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent30.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent30.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent30..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent30.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent30.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent30.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent30.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent30.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent30.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[30] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[30]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[30]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[30]) { + return read_hpm_counter(30); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter30h.yaml b/arch/csr/Zihpm/mhpmcounter30h.yaml index 6d9d7d2f6..387568c41 100644 --- a/arch/csr/Zihpm/mhpmcounter30h.yaml +++ b/arch/csr/Zihpm/mhpmcounter30h.yaml @@ -4,26 +4,28 @@ -mhpmcounter30h: - long_name: Machine Hardware Performance Counter 30, Upper half - address: 0xB9E - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter30. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT30[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[30]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[30]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[30]) { - return read_hpm_counter(30)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter30h +long_name: Machine Hardware Performance Counter 30, Upper half +address: 0xB9E +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter30. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT30[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[30]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[30]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[30]) { + return read_hpm_counter(30)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter31.yaml b/arch/csr/Zihpm/mhpmcounter31.yaml index 2452e30f8..32c98cd50 100644 --- a/arch/csr/Zihpm/mhpmcounter31.yaml +++ b/arch/csr/Zihpm/mhpmcounter31.yaml @@ -4,47 +4,49 @@ -mhpmcounter31: - long_name: Machine Hardware Performance Counter 31 - address: 0xB1F - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[31] == true"] - -- - Performance counter for event selected in `mhpmevent31.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM31` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM31`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent31.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent31.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent31..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent31.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent31.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent31.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent31.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent31.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent31.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[31] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[31]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[31]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[31]) { - return read_hpm_counter(31); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter31 +long_name: Machine Hardware Performance Counter 31 +address: 0xB1F +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[31] == true"] + -- + Performance counter for event selected in `mhpmevent31.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM31` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM31`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent31.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent31.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent31..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent31.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent31.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent31.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent31.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent31.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent31.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[31] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[31]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[31]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[31]) { + return read_hpm_counter(31); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter31h.yaml b/arch/csr/Zihpm/mhpmcounter31h.yaml index d50b0827c..8d4922a73 100644 --- a/arch/csr/Zihpm/mhpmcounter31h.yaml +++ b/arch/csr/Zihpm/mhpmcounter31h.yaml @@ -4,26 +4,28 @@ -mhpmcounter31h: - long_name: Machine Hardware Performance Counter 31, Upper half - address: 0xB9F - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter31. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT31[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[31]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[31]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[31]) { - return read_hpm_counter(31)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter31h +long_name: Machine Hardware Performance Counter 31, Upper half +address: 0xB9F +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter31. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT31[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[31]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[31]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[31]) { + return read_hpm_counter(31)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter3h.yaml b/arch/csr/Zihpm/mhpmcounter3h.yaml index 32ff4884f..bd9d3e556 100644 --- a/arch/csr/Zihpm/mhpmcounter3h.yaml +++ b/arch/csr/Zihpm/mhpmcounter3h.yaml @@ -4,26 +4,28 @@ -mhpmcounter3h: - long_name: Machine Hardware Performance Counter 3, Upper half - address: 0xB83 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter3. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT3[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[3]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[3]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[3]) { - return read_hpm_counter(3)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter3h +long_name: Machine Hardware Performance Counter 3, Upper half +address: 0xB83 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter3. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT3[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[3]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[3]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[3]) { + return read_hpm_counter(3)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter4.yaml b/arch/csr/Zihpm/mhpmcounter4.yaml index 6f13e5199..eb5b9bbad 100644 --- a/arch/csr/Zihpm/mhpmcounter4.yaml +++ b/arch/csr/Zihpm/mhpmcounter4.yaml @@ -4,47 +4,49 @@ -mhpmcounter4: - long_name: Machine Hardware Performance Counter 4 - address: 0xB04 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[4] == true"] - -- - Performance counter for event selected in `mhpmevent4.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM4` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM4`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent4.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent4.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent4..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent4.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent4.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent4.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent4.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent4.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent4.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[4] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[4]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[4]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[4]) { - return read_hpm_counter(4); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter4 +long_name: Machine Hardware Performance Counter 4 +address: 0xB04 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[4] == true"] + -- + Performance counter for event selected in `mhpmevent4.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM4` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM4`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent4.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent4.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent4..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent4.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent4.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent4.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent4.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent4.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent4.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[4] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[4]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[4]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[4]) { + return read_hpm_counter(4); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter4h.yaml b/arch/csr/Zihpm/mhpmcounter4h.yaml index 96751620a..94ee0f926 100644 --- a/arch/csr/Zihpm/mhpmcounter4h.yaml +++ b/arch/csr/Zihpm/mhpmcounter4h.yaml @@ -4,26 +4,28 @@ -mhpmcounter4h: - long_name: Machine Hardware Performance Counter 4, Upper half - address: 0xB84 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter4. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT4[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[4]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[4]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[4]) { - return read_hpm_counter(4)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter4h +long_name: Machine Hardware Performance Counter 4, Upper half +address: 0xB84 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter4. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT4[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[4]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[4]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[4]) { + return read_hpm_counter(4)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter5.yaml b/arch/csr/Zihpm/mhpmcounter5.yaml index 7bb0cb1d3..5fa038e73 100644 --- a/arch/csr/Zihpm/mhpmcounter5.yaml +++ b/arch/csr/Zihpm/mhpmcounter5.yaml @@ -4,47 +4,49 @@ -mhpmcounter5: - long_name: Machine Hardware Performance Counter 5 - address: 0xB05 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[5] == true"] - -- - Performance counter for event selected in `mhpmevent5.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM5` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM5`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent5.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent5.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent5..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent5.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent5.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent5.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent5.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent5.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent5.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[5] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[5]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[5]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[5]) { - return read_hpm_counter(5); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter5 +long_name: Machine Hardware Performance Counter 5 +address: 0xB05 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[5] == true"] + -- + Performance counter for event selected in `mhpmevent5.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM5` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM5`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent5.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent5.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent5..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent5.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent5.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent5.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent5.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent5.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent5.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[5] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[5]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[5]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[5]) { + return read_hpm_counter(5); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter5h.yaml b/arch/csr/Zihpm/mhpmcounter5h.yaml index eefcf5c61..87008b5f8 100644 --- a/arch/csr/Zihpm/mhpmcounter5h.yaml +++ b/arch/csr/Zihpm/mhpmcounter5h.yaml @@ -4,26 +4,28 @@ -mhpmcounter5h: - long_name: Machine Hardware Performance Counter 5, Upper half - address: 0xB85 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter5. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT5[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[5]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[5]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[5]) { - return read_hpm_counter(5)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter5h +long_name: Machine Hardware Performance Counter 5, Upper half +address: 0xB85 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter5. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT5[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[5]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[5]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[5]) { + return read_hpm_counter(5)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter6.yaml b/arch/csr/Zihpm/mhpmcounter6.yaml index c79e6f7d7..97527ec46 100644 --- a/arch/csr/Zihpm/mhpmcounter6.yaml +++ b/arch/csr/Zihpm/mhpmcounter6.yaml @@ -4,47 +4,49 @@ -mhpmcounter6: - long_name: Machine Hardware Performance Counter 6 - address: 0xB06 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[6] == true"] - -- - Performance counter for event selected in `mhpmevent6.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM6` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM6`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent6.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent6.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent6..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent6.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent6.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent6.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent6.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent6.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent6.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[6] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[6]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[6]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[6]) { - return read_hpm_counter(6); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter6 +long_name: Machine Hardware Performance Counter 6 +address: 0xB06 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[6] == true"] + -- + Performance counter for event selected in `mhpmevent6.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM6` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM6`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent6.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent6.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent6..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent6.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent6.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent6.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent6.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent6.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent6.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[6] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[6]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[6]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[6]) { + return read_hpm_counter(6); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter6h.yaml b/arch/csr/Zihpm/mhpmcounter6h.yaml index 218d4b474..c51a0f487 100644 --- a/arch/csr/Zihpm/mhpmcounter6h.yaml +++ b/arch/csr/Zihpm/mhpmcounter6h.yaml @@ -4,26 +4,28 @@ -mhpmcounter6h: - long_name: Machine Hardware Performance Counter 6, Upper half - address: 0xB86 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter6. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT6[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[6]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[6]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[6]) { - return read_hpm_counter(6)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter6h +long_name: Machine Hardware Performance Counter 6, Upper half +address: 0xB86 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter6. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT6[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[6]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[6]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[6]) { + return read_hpm_counter(6)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter7.yaml b/arch/csr/Zihpm/mhpmcounter7.yaml index e26bfdcad..cfb4ba894 100644 --- a/arch/csr/Zihpm/mhpmcounter7.yaml +++ b/arch/csr/Zihpm/mhpmcounter7.yaml @@ -4,47 +4,49 @@ -mhpmcounter7: - long_name: Machine Hardware Performance Counter 7 - address: 0xB07 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[7] == true"] - -- - Performance counter for event selected in `mhpmevent7.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM7` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM7`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent7.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent7.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent7..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent7.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent7.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent7.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent7.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent7.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent7.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[7] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[7]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[7]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[7]) { - return read_hpm_counter(7); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter7 +long_name: Machine Hardware Performance Counter 7 +address: 0xB07 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[7] == true"] + -- + Performance counter for event selected in `mhpmevent7.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM7` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM7`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent7.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent7.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent7..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent7.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent7.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent7.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent7.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent7.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent7.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[7] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[7]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[7]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[7]) { + return read_hpm_counter(7); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter7h.yaml b/arch/csr/Zihpm/mhpmcounter7h.yaml index 7847f15fb..0d05d9c9c 100644 --- a/arch/csr/Zihpm/mhpmcounter7h.yaml +++ b/arch/csr/Zihpm/mhpmcounter7h.yaml @@ -4,26 +4,28 @@ -mhpmcounter7h: - long_name: Machine Hardware Performance Counter 7, Upper half - address: 0xB87 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter7. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT7[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[7]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[7]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[7]) { - return read_hpm_counter(7)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter7h +long_name: Machine Hardware Performance Counter 7, Upper half +address: 0xB87 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter7. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT7[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[7]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[7]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[7]) { + return read_hpm_counter(7)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter8.yaml b/arch/csr/Zihpm/mhpmcounter8.yaml index 05ed7e02d..2c71caa78 100644 --- a/arch/csr/Zihpm/mhpmcounter8.yaml +++ b/arch/csr/Zihpm/mhpmcounter8.yaml @@ -4,47 +4,49 @@ -mhpmcounter8: - long_name: Machine Hardware Performance Counter 8 - address: 0xB08 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[8] == true"] - -- - Performance counter for event selected in `mhpmevent8.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM8` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM8`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent8.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent8.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent8..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent8.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent8.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent8.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent8.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent8.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent8.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[8] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[8]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[8]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[8]) { - return read_hpm_counter(8); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter8 +long_name: Machine Hardware Performance Counter 8 +address: 0xB08 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[8] == true"] + -- + Performance counter for event selected in `mhpmevent8.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM8` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM8`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent8.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent8.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent8..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent8.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent8.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent8.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent8.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent8.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent8.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[8] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[8]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[8]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[8]) { + return read_hpm_counter(8); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter8h.yaml b/arch/csr/Zihpm/mhpmcounter8h.yaml index 75378f3a8..0df82e412 100644 --- a/arch/csr/Zihpm/mhpmcounter8h.yaml +++ b/arch/csr/Zihpm/mhpmcounter8h.yaml @@ -4,26 +4,28 @@ -mhpmcounter8h: - long_name: Machine Hardware Performance Counter 8, Upper half - address: 0xB88 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter8. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT8[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[8]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[8]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[8]) { - return read_hpm_counter(8)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter8h +long_name: Machine Hardware Performance Counter 8, Upper half +address: 0xB88 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter8. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT8[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[8]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[8]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[8]) { + return read_hpm_counter(8)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounter9.yaml b/arch/csr/Zihpm/mhpmcounter9.yaml index 102138a9d..73392f5f1 100644 --- a/arch/csr/Zihpm/mhpmcounter9.yaml +++ b/arch/csr/Zihpm/mhpmcounter9.yaml @@ -4,47 +4,49 @@ -mhpmcounter9: - long_name: Machine Hardware Performance Counter 9 - address: 0xB09 - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[9] == true"] - -- - Performance counter for event selected in `mhpmevent9.EVENT`. - - Increments every time event occurs unless: - - * `mcountinhibit.HPM9` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM9`<%- end -%> is set - <%- if ext?(:Sscofpmf) -%> - * `mhpmevent9.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mhpmevent9.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent9..SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mhpmevent9.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent9.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mhpmevent9.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent9.SINH`<%- end -%> is set and the current privilege level is VS - * `mhpmevent9.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent9.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - -- - - [when="HPM_COUNTER_EN[9] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - - type(): 'return (HPM_COUNTER_EN[9]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[9]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[9]) { - return read_hpm_counter(9); - } else { - return 0; - } +$schema: csr_schema.json# +kind: csr +name: mhpmcounter9 +long_name: Machine Hardware Performance Counter 9 +address: 0xB09 +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[9] == true"] + -- + Performance counter for event selected in `mhpmevent9.EVENT`. + + Increments every time event occurs unless: + + * `mcountinhibit.HPM9` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM9`<%- end -%> is set + <%- if ext?(:Sscofpmf) -%> + * `mhpmevent9.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mhpmevent9.SINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent9..SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mhpmevent9.UINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent9.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mhpmevent9.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent9.SINH`<%- end -%> is set and the current privilege level is VS + * `mhpmevent9.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `hpmevent9.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + -- + + [when="HPM_COUNTER_EN[9] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + + type(): 'return (HPM_COUNTER_EN[9]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[9]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[9]) { + return read_hpm_counter(9); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounter9h.yaml b/arch/csr/Zihpm/mhpmcounter9h.yaml index e5255ec84..b3bb95d7c 100644 --- a/arch/csr/Zihpm/mhpmcounter9h.yaml +++ b/arch/csr/Zihpm/mhpmcounter9h.yaml @@ -4,26 +4,28 @@ -mhpmcounter9h: - long_name: Machine Hardware Performance Counter 9, Upper half - address: 0xB89 - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter9. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT9[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[9]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[9]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[9]) { - return read_hpm_counter(9)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: mhpmcounter9h +long_name: Machine Hardware Performance Counter 9, Upper half +address: 0xB89 +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter9. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT9[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[9]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[9]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[9]) { + return read_hpm_counter(9)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmcounterN.layout b/arch/csr/Zihpm/mhpmcounterN.layout index e55fef828..8b6fd187d 100644 --- a/arch/csr/Zihpm/mhpmcounterN.layout +++ b/arch/csr/Zihpm/mhpmcounterN.layout @@ -2,47 +2,49 @@ <%- raise("'hpm_num' must be defined") if hpm_num.nil? -%> -<%= "mhpmcounter#{hpm_num}" %>: - long_name: Machine Hardware Performance Counter <%= hpm_num %> - address: <%= "0x" + (0xB00 + hpm_num).to_s(16).upcase %> - priv_mode: M - length: 64 - description: Programmable hardware performance counter. - definedBy: Smhpm - fields: - COUNT: - location: 63-0 - description: | - [when="HPM_COUNTER_EN[<%= hpm_num %>] == true"] - -- - Performance counter for event selected in `mhpmevent<%= hpm_num %>.EVENT`. +$schema: csr_schema.json# +kind: csr +name: <%= "mhpmcounter#{hpm_num}" %> +long_name: Machine Hardware Performance Counter <%= hpm_num %> +address: <%= "0x" + (0xB00 + hpm_num).to_s(16).upcase %> +priv_mode: M +length: 64 +description: Programmable hardware performance counter. +definedBy: Smhpm +fields: + COUNT: + location: 63-0 + description: | + [when="HPM_COUNTER_EN[<%= hpm_num %>] == true"] + -- + Performance counter for event selected in `mhpmevent<%= hpm_num %>.EVENT`. - Increments every time event occurs unless: + Increments every time event occurs unless: - * `mcountinhibit.HPM<%= hpm_num %>` <%%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM<%= hpm_num %>`<%%- end -%> is set - <%%- if ext?(:Sscofpmf) -%> - * `mhpmevent<%= hpm_num %>.MINH` is set and the current privilege level is M - <%%- if ext?(:S) -%> - * `mhpmevent<%= hpm_num %>.SINH` <%%- if ext?(:Ssccfg) -%>or its alias `hpmevent<%= hpm_num %>..SINH`<%%- end -%> is set and the current privilege level is (H)S - <%%- end -%> - <%%- if ext?(:U) -%> - * `mhpmevent<%= hpm_num %>.UINH` <%%- if ext?(:Ssccfg) -%>or its alias `hpmevent<%= hpm_num %>.SINH`<%%- end -%> is set and the current privilege level is U - <%%- end -%> - <%%- if ext?(:H) -%> - * `mhpmevent<%= hpm_num %>.VSINH` <%%- if ext?(:Ssccfg) -%>or its alias `hpmevent<%= hpm_num %>.SINH`<%%- end -%> is set and the current privilege level is VS - * `mhpmevent<%= hpm_num %>.VUINH` <%%- if ext?(:Ssccfg) -%>or its alias `hpmevent<%= hpm_num %>.SINH`<%%- end -%> is set and the current privilege level is VU - <%%- end -%> - <%%- end -%> - -- + * `mcountinhibit.HPM<%= hpm_num %>` <%%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.HPM<%= hpm_num %>`<%%- end -%> is set + <%%- if ext?(:Sscofpmf) -%> + * `mhpmevent<%= hpm_num %>.MINH` is set and the current privilege level is M + <%%- if ext?(:S) -%> + * `mhpmevent<%= hpm_num %>.SINH` <%%- if ext?(:Ssccfg) -%>or its alias `hpmevent<%= hpm_num %>..SINH`<%%- end -%> is set and the current privilege level is (H)S + <%%- end -%> + <%%- if ext?(:U) -%> + * `mhpmevent<%= hpm_num %>.UINH` <%%- if ext?(:Ssccfg) -%>or its alias `hpmevent<%= hpm_num %>.SINH`<%%- end -%> is set and the current privilege level is U + <%%- end -%> + <%%- if ext?(:H) -%> + * `mhpmevent<%= hpm_num %>.VSINH` <%%- if ext?(:Ssccfg) -%>or its alias `hpmevent<%= hpm_num %>.SINH`<%%- end -%> is set and the current privilege level is VS + * `mhpmevent<%= hpm_num %>.VUINH` <%%- if ext?(:Ssccfg) -%>or its alias `hpmevent<%= hpm_num %>.SINH`<%%- end -%> is set and the current privilege level is VU + <%%- end -%> + <%%- end -%> + -- - [when="HPM_COUNTER_EN[<%= hpm_num %>] == false"] - Unimplemented performance counter. Must be read-only 0 (access does not cause trap). + [when="HPM_COUNTER_EN[<%= hpm_num %>] == false"] + Unimplemented performance counter. Must be read-only 0 (access does not cause trap). - type(): 'return (HPM_COUNTER_EN[<%= hpm_num %>]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[<%= hpm_num %>]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return read_hpm_counter(<%= hpm_num %>); - } else { - return 0; - } + type(): 'return (HPM_COUNTER_EN[<%= hpm_num %>]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[<%= hpm_num %>]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return read_hpm_counter(<%= hpm_num %>); + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmcounterNh.layout b/arch/csr/Zihpm/mhpmcounterNh.layout index 54dc2af20..b9f4b2f14 100644 --- a/arch/csr/Zihpm/mhpmcounterNh.layout +++ b/arch/csr/Zihpm/mhpmcounterNh.layout @@ -2,26 +2,28 @@ <%- raise "'hpm_num' must be defined" if hpm_num.nil? -%> -<%= "mhpmcounter#{hpm_num}h" %>: - long_name: Machine Hardware Performance Counter <%= hpm_num %>, Upper half - address: <%= "0x" + (0xB80 + hpm_num).to_s(16).upcase %> - priv_mode: M - length: 32 - base: 32 - description: | - Upper half of mhpmcounter<%= hpm_num %>. - definedBy: Smhpm - fields: - COUNT: - location: 32-0 - alias: mhpmcounter.COUNT<%= hpm_num %>[63:32] - description: | - Upper bits of counter. - type(): 'return (HPM_COUNTER_EN[<%= hpm_num %>]) ? CsrFieldType::RWH : CsrFieldType::RO;' - reset_value(): 'return (HPM_COUNTER_EN[<%= hpm_num %>]) ? UNDEFINED_LEGAL : 0;' - sw_read(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return read_hpm_counter(<%= hpm_num %>)[63:32]; - } else { - return 0; - } \ No newline at end of file +$schema: csr_schema.json# +kind: csr +name: <%= "mhpmcounter#{hpm_num}h" %> +long_name: Machine Hardware Performance Counter <%= hpm_num %>, Upper half +address: <%= "0x" + (0xB80 + hpm_num).to_s(16).upcase %> +priv_mode: M +length: 32 +base: 32 +description: | + Upper half of mhpmcounter<%= hpm_num %>. +definedBy: Smhpm +fields: + COUNT: + location: 32-0 + alias: mhpmcounter.COUNT<%= hpm_num %>[63:32] + description: | + Upper bits of counter. + type(): 'return (HPM_COUNTER_EN[<%= hpm_num %>]) ? CsrFieldType::RWH : CsrFieldType::RO;' + reset_value(): 'return (HPM_COUNTER_EN[<%= hpm_num %>]) ? UNDEFINED_LEGAL : 0;' +sw_read(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return read_hpm_counter(<%= hpm_num %>)[63:32]; + } else { + return 0; + } \ No newline at end of file diff --git a/arch/csr/Zihpm/mhpmevent10.yaml b/arch/csr/Zihpm/mhpmevent10.yaml index 49f943f1f..9b56c7491 100644 --- a/arch/csr/Zihpm/mhpmevent10.yaml +++ b/arch/csr/Zihpm/mhpmevent10.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent10: - long_name: Machine Hardware Performance Counter 10 Control - address: 0x32A - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent10 +long_name: Machine Hardware Performance Counter 10 Control +address: 0x32A +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter10 overflows. - type(): | - if (HPM_COUNTER_EN[10]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[10]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter10 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[10]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[10]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter10 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[10] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[10] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter10 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[10] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[10] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter10 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[10] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter10 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[10] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter10`. - type(): | - if (HPM_COUNTER_EN[10]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[10]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter10 overflows. + type(): | + if (HPM_COUNTER_EN[10]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[10]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter10 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[10]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[10]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter10 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[10] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[10] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter10 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[10] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[10] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter10 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[10] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter10 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[10] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter10`. + type(): | + if (HPM_COUNTER_EN[10]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[10]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent10h.yaml b/arch/csr/Zihpm/mhpmevent10h.yaml index 33985c91b..9fe80eb61 100644 --- a/arch/csr/Zihpm/mhpmevent10h.yaml +++ b/arch/csr/Zihpm/mhpmevent10h.yaml @@ -4,140 +4,142 @@ -mhpmevent10h: - long_name: Machine Hardware Performance Counter 10 Control, High half - address: 0x72A - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent10`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent10h +long_name: Machine Hardware Performance Counter 10 Control, High half +address: 0x72A +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent10`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent10.OF - description: | - Alias of mhpmevent10.OF. - type(): | - if (HPM_COUNTER_EN[10]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[10]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent10.MINH - description: | - Alias of mhpmevent10.MINH. - type(): | - if (HPM_COUNTER_EN[10]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[10]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent10.SINH - description: | - Alias of mhpmevent10.SINH. - type(): | - if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent10.UINH - description: | - Alias of mhpmevent10.UINH. - type(): | - if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent10.VSINH - description: | - Alias of mhpmevent10.VSINH. - type(): | - if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent10.VUINH - description: | - Alias of mhpmevent10.VUINH. - type(): | - if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter10`. - alias: mhpmevent10.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[10]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[10]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent10.OF + description: | + Alias of mhpmevent10.OF. + type(): | + if (HPM_COUNTER_EN[10]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[10]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent10.MINH + description: | + Alias of mhpmevent10.MINH. + type(): | + if (HPM_COUNTER_EN[10]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[10]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent10.SINH + description: | + Alias of mhpmevent10.SINH. + type(): | + if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent10.UINH + description: | + Alias of mhpmevent10.UINH. + type(): | + if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent10.VSINH + description: | + Alias of mhpmevent10.VSINH. + type(): | + if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent10.VUINH + description: | + Alias of mhpmevent10.VUINH. + type(): | + if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[10]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter10`. + alias: mhpmevent10.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[10]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[10]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent11.yaml b/arch/csr/Zihpm/mhpmevent11.yaml index 692b1a5b4..500c11cbc 100644 --- a/arch/csr/Zihpm/mhpmevent11.yaml +++ b/arch/csr/Zihpm/mhpmevent11.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent11: - long_name: Machine Hardware Performance Counter 11 Control - address: 0x32B - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent11 +long_name: Machine Hardware Performance Counter 11 Control +address: 0x32B +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter11 overflows. - type(): | - if (HPM_COUNTER_EN[11]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[11]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter11 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[11]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[11]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter11 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[11] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[11] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter11 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[11] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[11] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter11 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[11] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter11 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[11] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter11`. - type(): | - if (HPM_COUNTER_EN[11]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[11]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter11 overflows. + type(): | + if (HPM_COUNTER_EN[11]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[11]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter11 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[11]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[11]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter11 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[11] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[11] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter11 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[11] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[11] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter11 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[11] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter11 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[11] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter11`. + type(): | + if (HPM_COUNTER_EN[11]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[11]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent11h.yaml b/arch/csr/Zihpm/mhpmevent11h.yaml index fd6917bf8..7d1b6e997 100644 --- a/arch/csr/Zihpm/mhpmevent11h.yaml +++ b/arch/csr/Zihpm/mhpmevent11h.yaml @@ -4,140 +4,142 @@ -mhpmevent11h: - long_name: Machine Hardware Performance Counter 11 Control, High half - address: 0x72B - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent11`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent11h +long_name: Machine Hardware Performance Counter 11 Control, High half +address: 0x72B +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent11`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent11.OF - description: | - Alias of mhpmevent11.OF. - type(): | - if (HPM_COUNTER_EN[11]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[11]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent11.MINH - description: | - Alias of mhpmevent11.MINH. - type(): | - if (HPM_COUNTER_EN[11]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[11]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent11.SINH - description: | - Alias of mhpmevent11.SINH. - type(): | - if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent11.UINH - description: | - Alias of mhpmevent11.UINH. - type(): | - if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent11.VSINH - description: | - Alias of mhpmevent11.VSINH. - type(): | - if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent11.VUINH - description: | - Alias of mhpmevent11.VUINH. - type(): | - if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter11`. - alias: mhpmevent11.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[11]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[11]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent11.OF + description: | + Alias of mhpmevent11.OF. + type(): | + if (HPM_COUNTER_EN[11]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[11]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent11.MINH + description: | + Alias of mhpmevent11.MINH. + type(): | + if (HPM_COUNTER_EN[11]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[11]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent11.SINH + description: | + Alias of mhpmevent11.SINH. + type(): | + if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent11.UINH + description: | + Alias of mhpmevent11.UINH. + type(): | + if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent11.VSINH + description: | + Alias of mhpmevent11.VSINH. + type(): | + if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent11.VUINH + description: | + Alias of mhpmevent11.VUINH. + type(): | + if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[11]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter11`. + alias: mhpmevent11.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[11]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[11]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent12.yaml b/arch/csr/Zihpm/mhpmevent12.yaml index 93812b58b..3e06293c7 100644 --- a/arch/csr/Zihpm/mhpmevent12.yaml +++ b/arch/csr/Zihpm/mhpmevent12.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent12: - long_name: Machine Hardware Performance Counter 12 Control - address: 0x32C - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent12 +long_name: Machine Hardware Performance Counter 12 Control +address: 0x32C +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter12 overflows. - type(): | - if (HPM_COUNTER_EN[12]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[12]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter12 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[12]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[12]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter12 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[12] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[12] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter12 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[12] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[12] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter12 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[12] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter12 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[12] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter12`. - type(): | - if (HPM_COUNTER_EN[12]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[12]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter12 overflows. + type(): | + if (HPM_COUNTER_EN[12]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[12]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter12 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[12]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[12]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter12 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[12] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[12] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter12 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[12] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[12] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter12 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[12] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter12 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[12] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter12`. + type(): | + if (HPM_COUNTER_EN[12]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[12]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent12h.yaml b/arch/csr/Zihpm/mhpmevent12h.yaml index 309b4d079..054594b0d 100644 --- a/arch/csr/Zihpm/mhpmevent12h.yaml +++ b/arch/csr/Zihpm/mhpmevent12h.yaml @@ -4,140 +4,142 @@ -mhpmevent12h: - long_name: Machine Hardware Performance Counter 12 Control, High half - address: 0x72C - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent12`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent12h +long_name: Machine Hardware Performance Counter 12 Control, High half +address: 0x72C +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent12`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent12.OF - description: | - Alias of mhpmevent12.OF. - type(): | - if (HPM_COUNTER_EN[12]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[12]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent12.MINH - description: | - Alias of mhpmevent12.MINH. - type(): | - if (HPM_COUNTER_EN[12]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[12]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent12.SINH - description: | - Alias of mhpmevent12.SINH. - type(): | - if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent12.UINH - description: | - Alias of mhpmevent12.UINH. - type(): | - if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent12.VSINH - description: | - Alias of mhpmevent12.VSINH. - type(): | - if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent12.VUINH - description: | - Alias of mhpmevent12.VUINH. - type(): | - if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter12`. - alias: mhpmevent12.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[12]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[12]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent12.OF + description: | + Alias of mhpmevent12.OF. + type(): | + if (HPM_COUNTER_EN[12]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[12]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent12.MINH + description: | + Alias of mhpmevent12.MINH. + type(): | + if (HPM_COUNTER_EN[12]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[12]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent12.SINH + description: | + Alias of mhpmevent12.SINH. + type(): | + if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent12.UINH + description: | + Alias of mhpmevent12.UINH. + type(): | + if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent12.VSINH + description: | + Alias of mhpmevent12.VSINH. + type(): | + if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent12.VUINH + description: | + Alias of mhpmevent12.VUINH. + type(): | + if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[12]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter12`. + alias: mhpmevent12.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[12]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[12]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent13.yaml b/arch/csr/Zihpm/mhpmevent13.yaml index 55dadc5fe..5b4d051ba 100644 --- a/arch/csr/Zihpm/mhpmevent13.yaml +++ b/arch/csr/Zihpm/mhpmevent13.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent13: - long_name: Machine Hardware Performance Counter 13 Control - address: 0x32D - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent13 +long_name: Machine Hardware Performance Counter 13 Control +address: 0x32D +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter13 overflows. - type(): | - if (HPM_COUNTER_EN[13]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[13]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter13 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[13]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[13]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter13 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[13] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[13] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter13 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[13] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[13] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter13 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[13] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter13 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[13] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter13`. - type(): | - if (HPM_COUNTER_EN[13]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[13]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter13 overflows. + type(): | + if (HPM_COUNTER_EN[13]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[13]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter13 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[13]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[13]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter13 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[13] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[13] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter13 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[13] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[13] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter13 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[13] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter13 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[13] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter13`. + type(): | + if (HPM_COUNTER_EN[13]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[13]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent13h.yaml b/arch/csr/Zihpm/mhpmevent13h.yaml index 31db383e0..74ed46fde 100644 --- a/arch/csr/Zihpm/mhpmevent13h.yaml +++ b/arch/csr/Zihpm/mhpmevent13h.yaml @@ -4,140 +4,142 @@ -mhpmevent13h: - long_name: Machine Hardware Performance Counter 13 Control, High half - address: 0x72D - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent13`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent13h +long_name: Machine Hardware Performance Counter 13 Control, High half +address: 0x72D +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent13`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent13.OF - description: | - Alias of mhpmevent13.OF. - type(): | - if (HPM_COUNTER_EN[13]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[13]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent13.MINH - description: | - Alias of mhpmevent13.MINH. - type(): | - if (HPM_COUNTER_EN[13]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[13]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent13.SINH - description: | - Alias of mhpmevent13.SINH. - type(): | - if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent13.UINH - description: | - Alias of mhpmevent13.UINH. - type(): | - if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent13.VSINH - description: | - Alias of mhpmevent13.VSINH. - type(): | - if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent13.VUINH - description: | - Alias of mhpmevent13.VUINH. - type(): | - if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter13`. - alias: mhpmevent13.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[13]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[13]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent13.OF + description: | + Alias of mhpmevent13.OF. + type(): | + if (HPM_COUNTER_EN[13]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[13]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent13.MINH + description: | + Alias of mhpmevent13.MINH. + type(): | + if (HPM_COUNTER_EN[13]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[13]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent13.SINH + description: | + Alias of mhpmevent13.SINH. + type(): | + if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent13.UINH + description: | + Alias of mhpmevent13.UINH. + type(): | + if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent13.VSINH + description: | + Alias of mhpmevent13.VSINH. + type(): | + if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent13.VUINH + description: | + Alias of mhpmevent13.VUINH. + type(): | + if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[13]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter13`. + alias: mhpmevent13.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[13]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[13]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent14.yaml b/arch/csr/Zihpm/mhpmevent14.yaml index 338a1a98d..5b09f4368 100644 --- a/arch/csr/Zihpm/mhpmevent14.yaml +++ b/arch/csr/Zihpm/mhpmevent14.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent14: - long_name: Machine Hardware Performance Counter 14 Control - address: 0x32E - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent14 +long_name: Machine Hardware Performance Counter 14 Control +address: 0x32E +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter14 overflows. - type(): | - if (HPM_COUNTER_EN[14]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[14]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter14 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[14]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[14]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter14 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[14] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[14] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter14 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[14] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[14] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter14 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[14] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter14 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[14] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter14`. - type(): | - if (HPM_COUNTER_EN[14]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[14]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter14 overflows. + type(): | + if (HPM_COUNTER_EN[14]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[14]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter14 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[14]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[14]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter14 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[14] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[14] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter14 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[14] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[14] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter14 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[14] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter14 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[14] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter14`. + type(): | + if (HPM_COUNTER_EN[14]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[14]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent14h.yaml b/arch/csr/Zihpm/mhpmevent14h.yaml index 879e3f0e9..eb395e86d 100644 --- a/arch/csr/Zihpm/mhpmevent14h.yaml +++ b/arch/csr/Zihpm/mhpmevent14h.yaml @@ -4,140 +4,142 @@ -mhpmevent14h: - long_name: Machine Hardware Performance Counter 14 Control, High half - address: 0x72E - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent14`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent14h +long_name: Machine Hardware Performance Counter 14 Control, High half +address: 0x72E +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent14`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent14.OF - description: | - Alias of mhpmevent14.OF. - type(): | - if (HPM_COUNTER_EN[14]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[14]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent14.MINH - description: | - Alias of mhpmevent14.MINH. - type(): | - if (HPM_COUNTER_EN[14]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[14]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent14.SINH - description: | - Alias of mhpmevent14.SINH. - type(): | - if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent14.UINH - description: | - Alias of mhpmevent14.UINH. - type(): | - if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent14.VSINH - description: | - Alias of mhpmevent14.VSINH. - type(): | - if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent14.VUINH - description: | - Alias of mhpmevent14.VUINH. - type(): | - if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter14`. - alias: mhpmevent14.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[14]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[14]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent14.OF + description: | + Alias of mhpmevent14.OF. + type(): | + if (HPM_COUNTER_EN[14]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[14]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent14.MINH + description: | + Alias of mhpmevent14.MINH. + type(): | + if (HPM_COUNTER_EN[14]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[14]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent14.SINH + description: | + Alias of mhpmevent14.SINH. + type(): | + if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent14.UINH + description: | + Alias of mhpmevent14.UINH. + type(): | + if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent14.VSINH + description: | + Alias of mhpmevent14.VSINH. + type(): | + if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent14.VUINH + description: | + Alias of mhpmevent14.VUINH. + type(): | + if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[14]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter14`. + alias: mhpmevent14.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[14]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[14]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent15.yaml b/arch/csr/Zihpm/mhpmevent15.yaml index 52af89e2b..5c72db6da 100644 --- a/arch/csr/Zihpm/mhpmevent15.yaml +++ b/arch/csr/Zihpm/mhpmevent15.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent15: - long_name: Machine Hardware Performance Counter 15 Control - address: 0x32F - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent15 +long_name: Machine Hardware Performance Counter 15 Control +address: 0x32F +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter15 overflows. - type(): | - if (HPM_COUNTER_EN[15]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[15]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter15 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[15]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[15]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter15 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[15] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[15] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter15 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[15] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[15] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter15 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[15] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter15 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[15] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter15`. - type(): | - if (HPM_COUNTER_EN[15]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[15]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter15 overflows. + type(): | + if (HPM_COUNTER_EN[15]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[15]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter15 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[15]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[15]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter15 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[15] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[15] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter15 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[15] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[15] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter15 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[15] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter15 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[15] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter15`. + type(): | + if (HPM_COUNTER_EN[15]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[15]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent15h.yaml b/arch/csr/Zihpm/mhpmevent15h.yaml index 9f6a7cf2e..2914c5aa4 100644 --- a/arch/csr/Zihpm/mhpmevent15h.yaml +++ b/arch/csr/Zihpm/mhpmevent15h.yaml @@ -4,140 +4,142 @@ -mhpmevent15h: - long_name: Machine Hardware Performance Counter 15 Control, High half - address: 0x72F - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent15`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent15h +long_name: Machine Hardware Performance Counter 15 Control, High half +address: 0x72F +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent15`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent15.OF - description: | - Alias of mhpmevent15.OF. - type(): | - if (HPM_COUNTER_EN[15]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[15]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent15.MINH - description: | - Alias of mhpmevent15.MINH. - type(): | - if (HPM_COUNTER_EN[15]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[15]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent15.SINH - description: | - Alias of mhpmevent15.SINH. - type(): | - if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent15.UINH - description: | - Alias of mhpmevent15.UINH. - type(): | - if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent15.VSINH - description: | - Alias of mhpmevent15.VSINH. - type(): | - if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent15.VUINH - description: | - Alias of mhpmevent15.VUINH. - type(): | - if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter15`. - alias: mhpmevent15.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[15]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[15]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent15.OF + description: | + Alias of mhpmevent15.OF. + type(): | + if (HPM_COUNTER_EN[15]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[15]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent15.MINH + description: | + Alias of mhpmevent15.MINH. + type(): | + if (HPM_COUNTER_EN[15]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[15]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent15.SINH + description: | + Alias of mhpmevent15.SINH. + type(): | + if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent15.UINH + description: | + Alias of mhpmevent15.UINH. + type(): | + if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent15.VSINH + description: | + Alias of mhpmevent15.VSINH. + type(): | + if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent15.VUINH + description: | + Alias of mhpmevent15.VUINH. + type(): | + if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[15]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter15`. + alias: mhpmevent15.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[15]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[15]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent16.yaml b/arch/csr/Zihpm/mhpmevent16.yaml index 2fd436ade..6eefa2918 100644 --- a/arch/csr/Zihpm/mhpmevent16.yaml +++ b/arch/csr/Zihpm/mhpmevent16.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent16: - long_name: Machine Hardware Performance Counter 16 Control - address: 0x330 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent16 +long_name: Machine Hardware Performance Counter 16 Control +address: 0x330 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter16 overflows. - type(): | - if (HPM_COUNTER_EN[16]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[16]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter16 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[16]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[16]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter16 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[16] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[16] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter16 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[16] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[16] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter16 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[16] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter16 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[16] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter16`. - type(): | - if (HPM_COUNTER_EN[16]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[16]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter16 overflows. + type(): | + if (HPM_COUNTER_EN[16]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[16]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter16 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[16]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[16]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter16 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[16] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[16] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter16 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[16] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[16] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter16 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[16] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter16 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[16] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter16`. + type(): | + if (HPM_COUNTER_EN[16]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[16]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent16h.yaml b/arch/csr/Zihpm/mhpmevent16h.yaml index e3a920bbb..86c4539a1 100644 --- a/arch/csr/Zihpm/mhpmevent16h.yaml +++ b/arch/csr/Zihpm/mhpmevent16h.yaml @@ -4,140 +4,142 @@ -mhpmevent16h: - long_name: Machine Hardware Performance Counter 16 Control, High half - address: 0x730 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent16`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent16h +long_name: Machine Hardware Performance Counter 16 Control, High half +address: 0x730 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent16`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent16.OF - description: | - Alias of mhpmevent16.OF. - type(): | - if (HPM_COUNTER_EN[16]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[16]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent16.MINH - description: | - Alias of mhpmevent16.MINH. - type(): | - if (HPM_COUNTER_EN[16]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[16]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent16.SINH - description: | - Alias of mhpmevent16.SINH. - type(): | - if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent16.UINH - description: | - Alias of mhpmevent16.UINH. - type(): | - if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent16.VSINH - description: | - Alias of mhpmevent16.VSINH. - type(): | - if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent16.VUINH - description: | - Alias of mhpmevent16.VUINH. - type(): | - if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter16`. - alias: mhpmevent16.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[16]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[16]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent16.OF + description: | + Alias of mhpmevent16.OF. + type(): | + if (HPM_COUNTER_EN[16]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[16]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent16.MINH + description: | + Alias of mhpmevent16.MINH. + type(): | + if (HPM_COUNTER_EN[16]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[16]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent16.SINH + description: | + Alias of mhpmevent16.SINH. + type(): | + if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent16.UINH + description: | + Alias of mhpmevent16.UINH. + type(): | + if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent16.VSINH + description: | + Alias of mhpmevent16.VSINH. + type(): | + if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent16.VUINH + description: | + Alias of mhpmevent16.VUINH. + type(): | + if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[16]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter16`. + alias: mhpmevent16.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[16]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[16]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent17.yaml b/arch/csr/Zihpm/mhpmevent17.yaml index 42fbcc358..235850d37 100644 --- a/arch/csr/Zihpm/mhpmevent17.yaml +++ b/arch/csr/Zihpm/mhpmevent17.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent17: - long_name: Machine Hardware Performance Counter 17 Control - address: 0x331 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent17 +long_name: Machine Hardware Performance Counter 17 Control +address: 0x331 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter17 overflows. - type(): | - if (HPM_COUNTER_EN[17]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[17]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter17 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[17]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[17]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter17 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[17] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[17] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter17 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[17] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[17] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter17 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[17] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter17 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[17] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter17`. - type(): | - if (HPM_COUNTER_EN[17]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[17]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter17 overflows. + type(): | + if (HPM_COUNTER_EN[17]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[17]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter17 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[17]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[17]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter17 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[17] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[17] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter17 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[17] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[17] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter17 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[17] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter17 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[17] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter17`. + type(): | + if (HPM_COUNTER_EN[17]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[17]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent17h.yaml b/arch/csr/Zihpm/mhpmevent17h.yaml index 77fb3e008..e73159f13 100644 --- a/arch/csr/Zihpm/mhpmevent17h.yaml +++ b/arch/csr/Zihpm/mhpmevent17h.yaml @@ -4,140 +4,142 @@ -mhpmevent17h: - long_name: Machine Hardware Performance Counter 17 Control, High half - address: 0x731 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent17`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent17h +long_name: Machine Hardware Performance Counter 17 Control, High half +address: 0x731 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent17`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent17.OF - description: | - Alias of mhpmevent17.OF. - type(): | - if (HPM_COUNTER_EN[17]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[17]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent17.MINH - description: | - Alias of mhpmevent17.MINH. - type(): | - if (HPM_COUNTER_EN[17]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[17]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent17.SINH - description: | - Alias of mhpmevent17.SINH. - type(): | - if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent17.UINH - description: | - Alias of mhpmevent17.UINH. - type(): | - if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent17.VSINH - description: | - Alias of mhpmevent17.VSINH. - type(): | - if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent17.VUINH - description: | - Alias of mhpmevent17.VUINH. - type(): | - if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter17`. - alias: mhpmevent17.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[17]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[17]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent17.OF + description: | + Alias of mhpmevent17.OF. + type(): | + if (HPM_COUNTER_EN[17]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[17]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent17.MINH + description: | + Alias of mhpmevent17.MINH. + type(): | + if (HPM_COUNTER_EN[17]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[17]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent17.SINH + description: | + Alias of mhpmevent17.SINH. + type(): | + if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent17.UINH + description: | + Alias of mhpmevent17.UINH. + type(): | + if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent17.VSINH + description: | + Alias of mhpmevent17.VSINH. + type(): | + if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent17.VUINH + description: | + Alias of mhpmevent17.VUINH. + type(): | + if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[17]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter17`. + alias: mhpmevent17.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[17]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[17]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent18.yaml b/arch/csr/Zihpm/mhpmevent18.yaml index c96e6b605..124d21a20 100644 --- a/arch/csr/Zihpm/mhpmevent18.yaml +++ b/arch/csr/Zihpm/mhpmevent18.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent18: - long_name: Machine Hardware Performance Counter 18 Control - address: 0x332 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent18 +long_name: Machine Hardware Performance Counter 18 Control +address: 0x332 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter18 overflows. - type(): | - if (HPM_COUNTER_EN[18]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[18]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter18 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[18]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[18]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter18 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[18] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[18] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter18 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[18] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[18] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter18 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[18] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter18 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[18] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter18`. - type(): | - if (HPM_COUNTER_EN[18]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[18]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter18 overflows. + type(): | + if (HPM_COUNTER_EN[18]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[18]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter18 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[18]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[18]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter18 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[18] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[18] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter18 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[18] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[18] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter18 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[18] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter18 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[18] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter18`. + type(): | + if (HPM_COUNTER_EN[18]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[18]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent18h.yaml b/arch/csr/Zihpm/mhpmevent18h.yaml index 3ad971886..5d8f55fdc 100644 --- a/arch/csr/Zihpm/mhpmevent18h.yaml +++ b/arch/csr/Zihpm/mhpmevent18h.yaml @@ -4,140 +4,142 @@ -mhpmevent18h: - long_name: Machine Hardware Performance Counter 18 Control, High half - address: 0x732 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent18`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent18h +long_name: Machine Hardware Performance Counter 18 Control, High half +address: 0x732 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent18`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent18.OF - description: | - Alias of mhpmevent18.OF. - type(): | - if (HPM_COUNTER_EN[18]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[18]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent18.MINH - description: | - Alias of mhpmevent18.MINH. - type(): | - if (HPM_COUNTER_EN[18]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[18]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent18.SINH - description: | - Alias of mhpmevent18.SINH. - type(): | - if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent18.UINH - description: | - Alias of mhpmevent18.UINH. - type(): | - if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent18.VSINH - description: | - Alias of mhpmevent18.VSINH. - type(): | - if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent18.VUINH - description: | - Alias of mhpmevent18.VUINH. - type(): | - if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter18`. - alias: mhpmevent18.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[18]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[18]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent18.OF + description: | + Alias of mhpmevent18.OF. + type(): | + if (HPM_COUNTER_EN[18]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[18]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent18.MINH + description: | + Alias of mhpmevent18.MINH. + type(): | + if (HPM_COUNTER_EN[18]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[18]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent18.SINH + description: | + Alias of mhpmevent18.SINH. + type(): | + if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent18.UINH + description: | + Alias of mhpmevent18.UINH. + type(): | + if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent18.VSINH + description: | + Alias of mhpmevent18.VSINH. + type(): | + if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent18.VUINH + description: | + Alias of mhpmevent18.VUINH. + type(): | + if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[18]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter18`. + alias: mhpmevent18.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[18]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[18]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent19.yaml b/arch/csr/Zihpm/mhpmevent19.yaml index 8116d7603..381680576 100644 --- a/arch/csr/Zihpm/mhpmevent19.yaml +++ b/arch/csr/Zihpm/mhpmevent19.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent19: - long_name: Machine Hardware Performance Counter 19 Control - address: 0x333 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent19 +long_name: Machine Hardware Performance Counter 19 Control +address: 0x333 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter19 overflows. - type(): | - if (HPM_COUNTER_EN[19]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[19]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter19 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[19]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[19]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter19 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[19] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[19] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter19 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[19] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[19] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter19 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[19] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter19 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[19] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter19`. - type(): | - if (HPM_COUNTER_EN[19]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[19]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter19 overflows. + type(): | + if (HPM_COUNTER_EN[19]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[19]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter19 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[19]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[19]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter19 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[19] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[19] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter19 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[19] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[19] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter19 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[19] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter19 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[19] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter19`. + type(): | + if (HPM_COUNTER_EN[19]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[19]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent19h.yaml b/arch/csr/Zihpm/mhpmevent19h.yaml index dfd023716..30cf36077 100644 --- a/arch/csr/Zihpm/mhpmevent19h.yaml +++ b/arch/csr/Zihpm/mhpmevent19h.yaml @@ -4,140 +4,142 @@ -mhpmevent19h: - long_name: Machine Hardware Performance Counter 19 Control, High half - address: 0x733 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent19`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent19h +long_name: Machine Hardware Performance Counter 19 Control, High half +address: 0x733 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent19`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent19.OF - description: | - Alias of mhpmevent19.OF. - type(): | - if (HPM_COUNTER_EN[19]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[19]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent19.MINH - description: | - Alias of mhpmevent19.MINH. - type(): | - if (HPM_COUNTER_EN[19]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[19]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent19.SINH - description: | - Alias of mhpmevent19.SINH. - type(): | - if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent19.UINH - description: | - Alias of mhpmevent19.UINH. - type(): | - if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent19.VSINH - description: | - Alias of mhpmevent19.VSINH. - type(): | - if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent19.VUINH - description: | - Alias of mhpmevent19.VUINH. - type(): | - if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter19`. - alias: mhpmevent19.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[19]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[19]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent19.OF + description: | + Alias of mhpmevent19.OF. + type(): | + if (HPM_COUNTER_EN[19]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[19]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent19.MINH + description: | + Alias of mhpmevent19.MINH. + type(): | + if (HPM_COUNTER_EN[19]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[19]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent19.SINH + description: | + Alias of mhpmevent19.SINH. + type(): | + if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent19.UINH + description: | + Alias of mhpmevent19.UINH. + type(): | + if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent19.VSINH + description: | + Alias of mhpmevent19.VSINH. + type(): | + if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent19.VUINH + description: | + Alias of mhpmevent19.VUINH. + type(): | + if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[19]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter19`. + alias: mhpmevent19.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[19]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[19]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent20.yaml b/arch/csr/Zihpm/mhpmevent20.yaml index fd59572d1..370a5c4ce 100644 --- a/arch/csr/Zihpm/mhpmevent20.yaml +++ b/arch/csr/Zihpm/mhpmevent20.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent20: - long_name: Machine Hardware Performance Counter 20 Control - address: 0x334 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent20 +long_name: Machine Hardware Performance Counter 20 Control +address: 0x334 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter20 overflows. - type(): | - if (HPM_COUNTER_EN[20]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[20]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter20 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[20]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[20]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter20 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[20] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[20] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter20 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[20] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[20] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter20 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[20] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter20 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[20] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter20`. - type(): | - if (HPM_COUNTER_EN[20]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[20]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter20 overflows. + type(): | + if (HPM_COUNTER_EN[20]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[20]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter20 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[20]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[20]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter20 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[20] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[20] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter20 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[20] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[20] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter20 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[20] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter20 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[20] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter20`. + type(): | + if (HPM_COUNTER_EN[20]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[20]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent20h.yaml b/arch/csr/Zihpm/mhpmevent20h.yaml index a0dedd7b0..1073830fd 100644 --- a/arch/csr/Zihpm/mhpmevent20h.yaml +++ b/arch/csr/Zihpm/mhpmevent20h.yaml @@ -4,140 +4,142 @@ -mhpmevent20h: - long_name: Machine Hardware Performance Counter 20 Control, High half - address: 0x734 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent20`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent20h +long_name: Machine Hardware Performance Counter 20 Control, High half +address: 0x734 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent20`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent20.OF - description: | - Alias of mhpmevent20.OF. - type(): | - if (HPM_COUNTER_EN[20]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[20]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent20.MINH - description: | - Alias of mhpmevent20.MINH. - type(): | - if (HPM_COUNTER_EN[20]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[20]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent20.SINH - description: | - Alias of mhpmevent20.SINH. - type(): | - if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent20.UINH - description: | - Alias of mhpmevent20.UINH. - type(): | - if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent20.VSINH - description: | - Alias of mhpmevent20.VSINH. - type(): | - if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent20.VUINH - description: | - Alias of mhpmevent20.VUINH. - type(): | - if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter20`. - alias: mhpmevent20.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[20]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[20]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent20.OF + description: | + Alias of mhpmevent20.OF. + type(): | + if (HPM_COUNTER_EN[20]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[20]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent20.MINH + description: | + Alias of mhpmevent20.MINH. + type(): | + if (HPM_COUNTER_EN[20]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[20]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent20.SINH + description: | + Alias of mhpmevent20.SINH. + type(): | + if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent20.UINH + description: | + Alias of mhpmevent20.UINH. + type(): | + if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent20.VSINH + description: | + Alias of mhpmevent20.VSINH. + type(): | + if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent20.VUINH + description: | + Alias of mhpmevent20.VUINH. + type(): | + if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[20]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter20`. + alias: mhpmevent20.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[20]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[20]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent21.yaml b/arch/csr/Zihpm/mhpmevent21.yaml index 61ad59019..9164044e1 100644 --- a/arch/csr/Zihpm/mhpmevent21.yaml +++ b/arch/csr/Zihpm/mhpmevent21.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent21: - long_name: Machine Hardware Performance Counter 21 Control - address: 0x335 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent21 +long_name: Machine Hardware Performance Counter 21 Control +address: 0x335 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter21 overflows. - type(): | - if (HPM_COUNTER_EN[21]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[21]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter21 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[21]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[21]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter21 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[21] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[21] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter21 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[21] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[21] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter21 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[21] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter21 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[21] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter21`. - type(): | - if (HPM_COUNTER_EN[21]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[21]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter21 overflows. + type(): | + if (HPM_COUNTER_EN[21]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[21]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter21 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[21]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[21]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter21 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[21] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[21] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter21 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[21] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[21] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter21 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[21] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter21 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[21] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter21`. + type(): | + if (HPM_COUNTER_EN[21]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[21]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent21h.yaml b/arch/csr/Zihpm/mhpmevent21h.yaml index 82aceb033..cbb2757da 100644 --- a/arch/csr/Zihpm/mhpmevent21h.yaml +++ b/arch/csr/Zihpm/mhpmevent21h.yaml @@ -4,140 +4,142 @@ -mhpmevent21h: - long_name: Machine Hardware Performance Counter 21 Control, High half - address: 0x735 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent21`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent21h +long_name: Machine Hardware Performance Counter 21 Control, High half +address: 0x735 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent21`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent21.OF - description: | - Alias of mhpmevent21.OF. - type(): | - if (HPM_COUNTER_EN[21]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[21]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent21.MINH - description: | - Alias of mhpmevent21.MINH. - type(): | - if (HPM_COUNTER_EN[21]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[21]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent21.SINH - description: | - Alias of mhpmevent21.SINH. - type(): | - if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent21.UINH - description: | - Alias of mhpmevent21.UINH. - type(): | - if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent21.VSINH - description: | - Alias of mhpmevent21.VSINH. - type(): | - if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent21.VUINH - description: | - Alias of mhpmevent21.VUINH. - type(): | - if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter21`. - alias: mhpmevent21.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[21]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[21]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent21.OF + description: | + Alias of mhpmevent21.OF. + type(): | + if (HPM_COUNTER_EN[21]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[21]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent21.MINH + description: | + Alias of mhpmevent21.MINH. + type(): | + if (HPM_COUNTER_EN[21]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[21]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent21.SINH + description: | + Alias of mhpmevent21.SINH. + type(): | + if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent21.UINH + description: | + Alias of mhpmevent21.UINH. + type(): | + if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent21.VSINH + description: | + Alias of mhpmevent21.VSINH. + type(): | + if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent21.VUINH + description: | + Alias of mhpmevent21.VUINH. + type(): | + if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[21]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter21`. + alias: mhpmevent21.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[21]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[21]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent22.yaml b/arch/csr/Zihpm/mhpmevent22.yaml index df980a163..a44146188 100644 --- a/arch/csr/Zihpm/mhpmevent22.yaml +++ b/arch/csr/Zihpm/mhpmevent22.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent22: - long_name: Machine Hardware Performance Counter 22 Control - address: 0x336 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent22 +long_name: Machine Hardware Performance Counter 22 Control +address: 0x336 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter22 overflows. - type(): | - if (HPM_COUNTER_EN[22]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[22]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter22 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[22]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[22]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter22 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[22] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[22] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter22 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[22] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[22] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter22 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[22] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter22 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[22] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter22`. - type(): | - if (HPM_COUNTER_EN[22]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[22]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter22 overflows. + type(): | + if (HPM_COUNTER_EN[22]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[22]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter22 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[22]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[22]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter22 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[22] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[22] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter22 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[22] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[22] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter22 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[22] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter22 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[22] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter22`. + type(): | + if (HPM_COUNTER_EN[22]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[22]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent22h.yaml b/arch/csr/Zihpm/mhpmevent22h.yaml index 3ec6a981b..1806b2789 100644 --- a/arch/csr/Zihpm/mhpmevent22h.yaml +++ b/arch/csr/Zihpm/mhpmevent22h.yaml @@ -4,140 +4,142 @@ -mhpmevent22h: - long_name: Machine Hardware Performance Counter 22 Control, High half - address: 0x736 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent22`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent22h +long_name: Machine Hardware Performance Counter 22 Control, High half +address: 0x736 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent22`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent22.OF - description: | - Alias of mhpmevent22.OF. - type(): | - if (HPM_COUNTER_EN[22]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[22]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent22.MINH - description: | - Alias of mhpmevent22.MINH. - type(): | - if (HPM_COUNTER_EN[22]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[22]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent22.SINH - description: | - Alias of mhpmevent22.SINH. - type(): | - if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent22.UINH - description: | - Alias of mhpmevent22.UINH. - type(): | - if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent22.VSINH - description: | - Alias of mhpmevent22.VSINH. - type(): | - if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent22.VUINH - description: | - Alias of mhpmevent22.VUINH. - type(): | - if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter22`. - alias: mhpmevent22.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[22]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[22]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent22.OF + description: | + Alias of mhpmevent22.OF. + type(): | + if (HPM_COUNTER_EN[22]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[22]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent22.MINH + description: | + Alias of mhpmevent22.MINH. + type(): | + if (HPM_COUNTER_EN[22]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[22]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent22.SINH + description: | + Alias of mhpmevent22.SINH. + type(): | + if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent22.UINH + description: | + Alias of mhpmevent22.UINH. + type(): | + if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent22.VSINH + description: | + Alias of mhpmevent22.VSINH. + type(): | + if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent22.VUINH + description: | + Alias of mhpmevent22.VUINH. + type(): | + if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[22]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter22`. + alias: mhpmevent22.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[22]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[22]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent23.yaml b/arch/csr/Zihpm/mhpmevent23.yaml index f53e389f3..0c3d7d2f7 100644 --- a/arch/csr/Zihpm/mhpmevent23.yaml +++ b/arch/csr/Zihpm/mhpmevent23.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent23: - long_name: Machine Hardware Performance Counter 23 Control - address: 0x337 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent23 +long_name: Machine Hardware Performance Counter 23 Control +address: 0x337 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter23 overflows. - type(): | - if (HPM_COUNTER_EN[23]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[23]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter23 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[23]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[23]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter23 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[23] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[23] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter23 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[23] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[23] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter23 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[23] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter23 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[23] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter23`. - type(): | - if (HPM_COUNTER_EN[23]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[23]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter23 overflows. + type(): | + if (HPM_COUNTER_EN[23]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[23]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter23 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[23]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[23]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter23 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[23] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[23] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter23 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[23] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[23] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter23 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[23] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter23 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[23] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter23`. + type(): | + if (HPM_COUNTER_EN[23]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[23]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent23h.yaml b/arch/csr/Zihpm/mhpmevent23h.yaml index f7a15e93d..41a9f0b02 100644 --- a/arch/csr/Zihpm/mhpmevent23h.yaml +++ b/arch/csr/Zihpm/mhpmevent23h.yaml @@ -4,140 +4,142 @@ -mhpmevent23h: - long_name: Machine Hardware Performance Counter 23 Control, High half - address: 0x737 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent23`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent23h +long_name: Machine Hardware Performance Counter 23 Control, High half +address: 0x737 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent23`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent23.OF - description: | - Alias of mhpmevent23.OF. - type(): | - if (HPM_COUNTER_EN[23]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[23]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent23.MINH - description: | - Alias of mhpmevent23.MINH. - type(): | - if (HPM_COUNTER_EN[23]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[23]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent23.SINH - description: | - Alias of mhpmevent23.SINH. - type(): | - if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent23.UINH - description: | - Alias of mhpmevent23.UINH. - type(): | - if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent23.VSINH - description: | - Alias of mhpmevent23.VSINH. - type(): | - if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent23.VUINH - description: | - Alias of mhpmevent23.VUINH. - type(): | - if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter23`. - alias: mhpmevent23.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[23]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[23]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent23.OF + description: | + Alias of mhpmevent23.OF. + type(): | + if (HPM_COUNTER_EN[23]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[23]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent23.MINH + description: | + Alias of mhpmevent23.MINH. + type(): | + if (HPM_COUNTER_EN[23]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[23]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent23.SINH + description: | + Alias of mhpmevent23.SINH. + type(): | + if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent23.UINH + description: | + Alias of mhpmevent23.UINH. + type(): | + if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent23.VSINH + description: | + Alias of mhpmevent23.VSINH. + type(): | + if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent23.VUINH + description: | + Alias of mhpmevent23.VUINH. + type(): | + if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[23]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter23`. + alias: mhpmevent23.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[23]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[23]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent24.yaml b/arch/csr/Zihpm/mhpmevent24.yaml index 8d1893cd3..b566e153c 100644 --- a/arch/csr/Zihpm/mhpmevent24.yaml +++ b/arch/csr/Zihpm/mhpmevent24.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent24: - long_name: Machine Hardware Performance Counter 24 Control - address: 0x338 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent24 +long_name: Machine Hardware Performance Counter 24 Control +address: 0x338 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter24 overflows. - type(): | - if (HPM_COUNTER_EN[24]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[24]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter24 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[24]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[24]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter24 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[24] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[24] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter24 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[24] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[24] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter24 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[24] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter24 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[24] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter24`. - type(): | - if (HPM_COUNTER_EN[24]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[24]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter24 overflows. + type(): | + if (HPM_COUNTER_EN[24]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[24]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter24 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[24]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[24]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter24 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[24] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[24] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter24 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[24] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[24] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter24 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[24] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter24 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[24] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter24`. + type(): | + if (HPM_COUNTER_EN[24]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[24]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent24h.yaml b/arch/csr/Zihpm/mhpmevent24h.yaml index eec7819c4..560463c51 100644 --- a/arch/csr/Zihpm/mhpmevent24h.yaml +++ b/arch/csr/Zihpm/mhpmevent24h.yaml @@ -4,140 +4,142 @@ -mhpmevent24h: - long_name: Machine Hardware Performance Counter 24 Control, High half - address: 0x738 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent24`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent24h +long_name: Machine Hardware Performance Counter 24 Control, High half +address: 0x738 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent24`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent24.OF - description: | - Alias of mhpmevent24.OF. - type(): | - if (HPM_COUNTER_EN[24]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[24]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent24.MINH - description: | - Alias of mhpmevent24.MINH. - type(): | - if (HPM_COUNTER_EN[24]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[24]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent24.SINH - description: | - Alias of mhpmevent24.SINH. - type(): | - if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent24.UINH - description: | - Alias of mhpmevent24.UINH. - type(): | - if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent24.VSINH - description: | - Alias of mhpmevent24.VSINH. - type(): | - if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent24.VUINH - description: | - Alias of mhpmevent24.VUINH. - type(): | - if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter24`. - alias: mhpmevent24.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[24]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[24]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent24.OF + description: | + Alias of mhpmevent24.OF. + type(): | + if (HPM_COUNTER_EN[24]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[24]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent24.MINH + description: | + Alias of mhpmevent24.MINH. + type(): | + if (HPM_COUNTER_EN[24]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[24]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent24.SINH + description: | + Alias of mhpmevent24.SINH. + type(): | + if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent24.UINH + description: | + Alias of mhpmevent24.UINH. + type(): | + if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent24.VSINH + description: | + Alias of mhpmevent24.VSINH. + type(): | + if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent24.VUINH + description: | + Alias of mhpmevent24.VUINH. + type(): | + if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[24]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter24`. + alias: mhpmevent24.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[24]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[24]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent25.yaml b/arch/csr/Zihpm/mhpmevent25.yaml index 84cf3a0ba..55879cabe 100644 --- a/arch/csr/Zihpm/mhpmevent25.yaml +++ b/arch/csr/Zihpm/mhpmevent25.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent25: - long_name: Machine Hardware Performance Counter 25 Control - address: 0x339 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent25 +long_name: Machine Hardware Performance Counter 25 Control +address: 0x339 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter25 overflows. - type(): | - if (HPM_COUNTER_EN[25]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[25]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter25 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[25]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[25]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter25 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[25] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[25] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter25 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[25] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[25] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter25 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[25] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter25 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[25] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter25`. - type(): | - if (HPM_COUNTER_EN[25]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[25]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter25 overflows. + type(): | + if (HPM_COUNTER_EN[25]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[25]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter25 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[25]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[25]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter25 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[25] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[25] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter25 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[25] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[25] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter25 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[25] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter25 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[25] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter25`. + type(): | + if (HPM_COUNTER_EN[25]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[25]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent25h.yaml b/arch/csr/Zihpm/mhpmevent25h.yaml index 9b7d27816..1eefa3bdf 100644 --- a/arch/csr/Zihpm/mhpmevent25h.yaml +++ b/arch/csr/Zihpm/mhpmevent25h.yaml @@ -4,140 +4,142 @@ -mhpmevent25h: - long_name: Machine Hardware Performance Counter 25 Control, High half - address: 0x739 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent25`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent25h +long_name: Machine Hardware Performance Counter 25 Control, High half +address: 0x739 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent25`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent25.OF - description: | - Alias of mhpmevent25.OF. - type(): | - if (HPM_COUNTER_EN[25]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[25]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent25.MINH - description: | - Alias of mhpmevent25.MINH. - type(): | - if (HPM_COUNTER_EN[25]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[25]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent25.SINH - description: | - Alias of mhpmevent25.SINH. - type(): | - if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent25.UINH - description: | - Alias of mhpmevent25.UINH. - type(): | - if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent25.VSINH - description: | - Alias of mhpmevent25.VSINH. - type(): | - if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent25.VUINH - description: | - Alias of mhpmevent25.VUINH. - type(): | - if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter25`. - alias: mhpmevent25.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[25]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[25]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent25.OF + description: | + Alias of mhpmevent25.OF. + type(): | + if (HPM_COUNTER_EN[25]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[25]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent25.MINH + description: | + Alias of mhpmevent25.MINH. + type(): | + if (HPM_COUNTER_EN[25]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[25]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent25.SINH + description: | + Alias of mhpmevent25.SINH. + type(): | + if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent25.UINH + description: | + Alias of mhpmevent25.UINH. + type(): | + if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent25.VSINH + description: | + Alias of mhpmevent25.VSINH. + type(): | + if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent25.VUINH + description: | + Alias of mhpmevent25.VUINH. + type(): | + if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[25]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter25`. + alias: mhpmevent25.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[25]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[25]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent26.yaml b/arch/csr/Zihpm/mhpmevent26.yaml index 3b16d2c81..0efdccb2a 100644 --- a/arch/csr/Zihpm/mhpmevent26.yaml +++ b/arch/csr/Zihpm/mhpmevent26.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent26: - long_name: Machine Hardware Performance Counter 26 Control - address: 0x33A - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent26 +long_name: Machine Hardware Performance Counter 26 Control +address: 0x33A +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter26 overflows. - type(): | - if (HPM_COUNTER_EN[26]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[26]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter26 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[26]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[26]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter26 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[26] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[26] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter26 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[26] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[26] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter26 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[26] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter26 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[26] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter26`. - type(): | - if (HPM_COUNTER_EN[26]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[26]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter26 overflows. + type(): | + if (HPM_COUNTER_EN[26]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[26]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter26 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[26]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[26]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter26 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[26] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[26] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter26 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[26] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[26] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter26 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[26] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter26 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[26] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter26`. + type(): | + if (HPM_COUNTER_EN[26]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[26]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent26h.yaml b/arch/csr/Zihpm/mhpmevent26h.yaml index b1386bfd0..73bd744a7 100644 --- a/arch/csr/Zihpm/mhpmevent26h.yaml +++ b/arch/csr/Zihpm/mhpmevent26h.yaml @@ -4,140 +4,142 @@ -mhpmevent26h: - long_name: Machine Hardware Performance Counter 26 Control, High half - address: 0x73A - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent26`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent26h +long_name: Machine Hardware Performance Counter 26 Control, High half +address: 0x73A +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent26`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent26.OF - description: | - Alias of mhpmevent26.OF. - type(): | - if (HPM_COUNTER_EN[26]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[26]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent26.MINH - description: | - Alias of mhpmevent26.MINH. - type(): | - if (HPM_COUNTER_EN[26]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[26]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent26.SINH - description: | - Alias of mhpmevent26.SINH. - type(): | - if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent26.UINH - description: | - Alias of mhpmevent26.UINH. - type(): | - if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent26.VSINH - description: | - Alias of mhpmevent26.VSINH. - type(): | - if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent26.VUINH - description: | - Alias of mhpmevent26.VUINH. - type(): | - if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter26`. - alias: mhpmevent26.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[26]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[26]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent26.OF + description: | + Alias of mhpmevent26.OF. + type(): | + if (HPM_COUNTER_EN[26]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[26]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent26.MINH + description: | + Alias of mhpmevent26.MINH. + type(): | + if (HPM_COUNTER_EN[26]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[26]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent26.SINH + description: | + Alias of mhpmevent26.SINH. + type(): | + if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent26.UINH + description: | + Alias of mhpmevent26.UINH. + type(): | + if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent26.VSINH + description: | + Alias of mhpmevent26.VSINH. + type(): | + if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent26.VUINH + description: | + Alias of mhpmevent26.VUINH. + type(): | + if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[26]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter26`. + alias: mhpmevent26.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[26]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[26]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent27.yaml b/arch/csr/Zihpm/mhpmevent27.yaml index 51b0c6288..22d5be09c 100644 --- a/arch/csr/Zihpm/mhpmevent27.yaml +++ b/arch/csr/Zihpm/mhpmevent27.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent27: - long_name: Machine Hardware Performance Counter 27 Control - address: 0x33B - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent27 +long_name: Machine Hardware Performance Counter 27 Control +address: 0x33B +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter27 overflows. - type(): | - if (HPM_COUNTER_EN[27]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[27]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter27 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[27]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[27]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter27 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[27] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[27] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter27 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[27] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[27] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter27 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[27] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter27 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[27] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter27`. - type(): | - if (HPM_COUNTER_EN[27]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[27]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter27 overflows. + type(): | + if (HPM_COUNTER_EN[27]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[27]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter27 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[27]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[27]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter27 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[27] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[27] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter27 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[27] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[27] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter27 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[27] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter27 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[27] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter27`. + type(): | + if (HPM_COUNTER_EN[27]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[27]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent27h.yaml b/arch/csr/Zihpm/mhpmevent27h.yaml index f38f7d9b0..cb1a55da6 100644 --- a/arch/csr/Zihpm/mhpmevent27h.yaml +++ b/arch/csr/Zihpm/mhpmevent27h.yaml @@ -4,140 +4,142 @@ -mhpmevent27h: - long_name: Machine Hardware Performance Counter 27 Control, High half - address: 0x73B - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent27`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent27h +long_name: Machine Hardware Performance Counter 27 Control, High half +address: 0x73B +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent27`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent27.OF - description: | - Alias of mhpmevent27.OF. - type(): | - if (HPM_COUNTER_EN[27]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[27]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent27.MINH - description: | - Alias of mhpmevent27.MINH. - type(): | - if (HPM_COUNTER_EN[27]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[27]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent27.SINH - description: | - Alias of mhpmevent27.SINH. - type(): | - if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent27.UINH - description: | - Alias of mhpmevent27.UINH. - type(): | - if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent27.VSINH - description: | - Alias of mhpmevent27.VSINH. - type(): | - if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent27.VUINH - description: | - Alias of mhpmevent27.VUINH. - type(): | - if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter27`. - alias: mhpmevent27.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[27]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[27]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent27.OF + description: | + Alias of mhpmevent27.OF. + type(): | + if (HPM_COUNTER_EN[27]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[27]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent27.MINH + description: | + Alias of mhpmevent27.MINH. + type(): | + if (HPM_COUNTER_EN[27]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[27]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent27.SINH + description: | + Alias of mhpmevent27.SINH. + type(): | + if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent27.UINH + description: | + Alias of mhpmevent27.UINH. + type(): | + if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent27.VSINH + description: | + Alias of mhpmevent27.VSINH. + type(): | + if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent27.VUINH + description: | + Alias of mhpmevent27.VUINH. + type(): | + if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[27]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter27`. + alias: mhpmevent27.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[27]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[27]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent28.yaml b/arch/csr/Zihpm/mhpmevent28.yaml index f63fdcc99..172b0e1aa 100644 --- a/arch/csr/Zihpm/mhpmevent28.yaml +++ b/arch/csr/Zihpm/mhpmevent28.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent28: - long_name: Machine Hardware Performance Counter 28 Control - address: 0x33C - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent28 +long_name: Machine Hardware Performance Counter 28 Control +address: 0x33C +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter28 overflows. - type(): | - if (HPM_COUNTER_EN[28]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[28]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter28 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[28]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[28]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter28 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[28] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[28] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter28 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[28] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[28] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter28 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[28] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter28 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[28] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter28`. - type(): | - if (HPM_COUNTER_EN[28]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[28]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter28 overflows. + type(): | + if (HPM_COUNTER_EN[28]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[28]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter28 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[28]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[28]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter28 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[28] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[28] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter28 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[28] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[28] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter28 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[28] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter28 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[28] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter28`. + type(): | + if (HPM_COUNTER_EN[28]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[28]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent28h.yaml b/arch/csr/Zihpm/mhpmevent28h.yaml index 48f7b8772..1f3bb09ab 100644 --- a/arch/csr/Zihpm/mhpmevent28h.yaml +++ b/arch/csr/Zihpm/mhpmevent28h.yaml @@ -4,140 +4,142 @@ -mhpmevent28h: - long_name: Machine Hardware Performance Counter 28 Control, High half - address: 0x73C - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent28`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent28h +long_name: Machine Hardware Performance Counter 28 Control, High half +address: 0x73C +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent28`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent28.OF - description: | - Alias of mhpmevent28.OF. - type(): | - if (HPM_COUNTER_EN[28]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[28]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent28.MINH - description: | - Alias of mhpmevent28.MINH. - type(): | - if (HPM_COUNTER_EN[28]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[28]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent28.SINH - description: | - Alias of mhpmevent28.SINH. - type(): | - if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent28.UINH - description: | - Alias of mhpmevent28.UINH. - type(): | - if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent28.VSINH - description: | - Alias of mhpmevent28.VSINH. - type(): | - if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent28.VUINH - description: | - Alias of mhpmevent28.VUINH. - type(): | - if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter28`. - alias: mhpmevent28.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[28]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[28]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent28.OF + description: | + Alias of mhpmevent28.OF. + type(): | + if (HPM_COUNTER_EN[28]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[28]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent28.MINH + description: | + Alias of mhpmevent28.MINH. + type(): | + if (HPM_COUNTER_EN[28]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[28]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent28.SINH + description: | + Alias of mhpmevent28.SINH. + type(): | + if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent28.UINH + description: | + Alias of mhpmevent28.UINH. + type(): | + if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent28.VSINH + description: | + Alias of mhpmevent28.VSINH. + type(): | + if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent28.VUINH + description: | + Alias of mhpmevent28.VUINH. + type(): | + if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[28]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter28`. + alias: mhpmevent28.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[28]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[28]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent29.yaml b/arch/csr/Zihpm/mhpmevent29.yaml index 3c5fd3a70..42bbe1ef8 100644 --- a/arch/csr/Zihpm/mhpmevent29.yaml +++ b/arch/csr/Zihpm/mhpmevent29.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent29: - long_name: Machine Hardware Performance Counter 29 Control - address: 0x33D - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent29 +long_name: Machine Hardware Performance Counter 29 Control +address: 0x33D +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter29 overflows. - type(): | - if (HPM_COUNTER_EN[29]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[29]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter29 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[29]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[29]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter29 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[29] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[29] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter29 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[29] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[29] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter29 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[29] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter29 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[29] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter29`. - type(): | - if (HPM_COUNTER_EN[29]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[29]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter29 overflows. + type(): | + if (HPM_COUNTER_EN[29]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[29]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter29 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[29]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[29]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter29 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[29] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[29] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter29 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[29] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[29] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter29 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[29] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter29 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[29] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter29`. + type(): | + if (HPM_COUNTER_EN[29]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[29]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent29h.yaml b/arch/csr/Zihpm/mhpmevent29h.yaml index 218bb4449..a7c41c7ab 100644 --- a/arch/csr/Zihpm/mhpmevent29h.yaml +++ b/arch/csr/Zihpm/mhpmevent29h.yaml @@ -4,140 +4,142 @@ -mhpmevent29h: - long_name: Machine Hardware Performance Counter 29 Control, High half - address: 0x73D - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent29`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent29h +long_name: Machine Hardware Performance Counter 29 Control, High half +address: 0x73D +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent29`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent29.OF - description: | - Alias of mhpmevent29.OF. - type(): | - if (HPM_COUNTER_EN[29]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[29]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent29.MINH - description: | - Alias of mhpmevent29.MINH. - type(): | - if (HPM_COUNTER_EN[29]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[29]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent29.SINH - description: | - Alias of mhpmevent29.SINH. - type(): | - if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent29.UINH - description: | - Alias of mhpmevent29.UINH. - type(): | - if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent29.VSINH - description: | - Alias of mhpmevent29.VSINH. - type(): | - if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent29.VUINH - description: | - Alias of mhpmevent29.VUINH. - type(): | - if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter29`. - alias: mhpmevent29.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[29]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[29]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent29.OF + description: | + Alias of mhpmevent29.OF. + type(): | + if (HPM_COUNTER_EN[29]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[29]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent29.MINH + description: | + Alias of mhpmevent29.MINH. + type(): | + if (HPM_COUNTER_EN[29]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[29]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent29.SINH + description: | + Alias of mhpmevent29.SINH. + type(): | + if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent29.UINH + description: | + Alias of mhpmevent29.UINH. + type(): | + if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent29.VSINH + description: | + Alias of mhpmevent29.VSINH. + type(): | + if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent29.VUINH + description: | + Alias of mhpmevent29.VUINH. + type(): | + if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[29]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter29`. + alias: mhpmevent29.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[29]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[29]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent3.yaml b/arch/csr/Zihpm/mhpmevent3.yaml index 7fcc89078..2f309d6d9 100644 --- a/arch/csr/Zihpm/mhpmevent3.yaml +++ b/arch/csr/Zihpm/mhpmevent3.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent3: - long_name: Machine Hardware Performance Counter 3 Control - address: 0x323 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent3 +long_name: Machine Hardware Performance Counter 3 Control +address: 0x323 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter3 overflows. - type(): | - if (HPM_COUNTER_EN[3]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[3]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter3 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[3]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[3]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter3 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[3] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[3] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter3 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[3] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[3] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter3 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[3] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter3 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[3] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter3`. - type(): | - if (HPM_COUNTER_EN[3]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[3]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter3 overflows. + type(): | + if (HPM_COUNTER_EN[3]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[3]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter3 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[3]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[3]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter3 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[3] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[3] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter3 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[3] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[3] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter3 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[3] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter3 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[3] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter3`. + type(): | + if (HPM_COUNTER_EN[3]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[3]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent30.yaml b/arch/csr/Zihpm/mhpmevent30.yaml index 9946bd04b..eb485ec4f 100644 --- a/arch/csr/Zihpm/mhpmevent30.yaml +++ b/arch/csr/Zihpm/mhpmevent30.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent30: - long_name: Machine Hardware Performance Counter 30 Control - address: 0x33E - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent30 +long_name: Machine Hardware Performance Counter 30 Control +address: 0x33E +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter30 overflows. - type(): | - if (HPM_COUNTER_EN[30]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[30]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter30 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[30]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[30]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter30 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[30] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[30] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter30 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[30] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[30] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter30 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[30] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter30 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[30] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter30`. - type(): | - if (HPM_COUNTER_EN[30]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[30]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter30 overflows. + type(): | + if (HPM_COUNTER_EN[30]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[30]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter30 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[30]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[30]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter30 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[30] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[30] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter30 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[30] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[30] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter30 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[30] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter30 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[30] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter30`. + type(): | + if (HPM_COUNTER_EN[30]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[30]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent30h.yaml b/arch/csr/Zihpm/mhpmevent30h.yaml index 722540287..3de930101 100644 --- a/arch/csr/Zihpm/mhpmevent30h.yaml +++ b/arch/csr/Zihpm/mhpmevent30h.yaml @@ -4,140 +4,142 @@ -mhpmevent30h: - long_name: Machine Hardware Performance Counter 30 Control, High half - address: 0x73E - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent30`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent30h +long_name: Machine Hardware Performance Counter 30 Control, High half +address: 0x73E +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent30`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent30.OF - description: | - Alias of mhpmevent30.OF. - type(): | - if (HPM_COUNTER_EN[30]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[30]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent30.MINH - description: | - Alias of mhpmevent30.MINH. - type(): | - if (HPM_COUNTER_EN[30]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[30]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent30.SINH - description: | - Alias of mhpmevent30.SINH. - type(): | - if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent30.UINH - description: | - Alias of mhpmevent30.UINH. - type(): | - if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent30.VSINH - description: | - Alias of mhpmevent30.VSINH. - type(): | - if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent30.VUINH - description: | - Alias of mhpmevent30.VUINH. - type(): | - if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter30`. - alias: mhpmevent30.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[30]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[30]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent30.OF + description: | + Alias of mhpmevent30.OF. + type(): | + if (HPM_COUNTER_EN[30]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[30]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent30.MINH + description: | + Alias of mhpmevent30.MINH. + type(): | + if (HPM_COUNTER_EN[30]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[30]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent30.SINH + description: | + Alias of mhpmevent30.SINH. + type(): | + if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent30.UINH + description: | + Alias of mhpmevent30.UINH. + type(): | + if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent30.VSINH + description: | + Alias of mhpmevent30.VSINH. + type(): | + if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent30.VUINH + description: | + Alias of mhpmevent30.VUINH. + type(): | + if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[30]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter30`. + alias: mhpmevent30.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[30]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[30]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent31.yaml b/arch/csr/Zihpm/mhpmevent31.yaml index e85dd66d5..2e19278f2 100644 --- a/arch/csr/Zihpm/mhpmevent31.yaml +++ b/arch/csr/Zihpm/mhpmevent31.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent31: - long_name: Machine Hardware Performance Counter 31 Control - address: 0x33F - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent31 +long_name: Machine Hardware Performance Counter 31 Control +address: 0x33F +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter31 overflows. - type(): | - if (HPM_COUNTER_EN[31]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[31]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter31 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[31]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[31]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter31 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[31] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[31] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter31 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[31] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[31] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter31 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[31] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter31 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[31] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter31`. - type(): | - if (HPM_COUNTER_EN[31]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[31]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter31 overflows. + type(): | + if (HPM_COUNTER_EN[31]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[31]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter31 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[31]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[31]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter31 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[31] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[31] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter31 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[31] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[31] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter31 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[31] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter31 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[31] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter31`. + type(): | + if (HPM_COUNTER_EN[31]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[31]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent31h.yaml b/arch/csr/Zihpm/mhpmevent31h.yaml index c20579128..7e03cc52e 100644 --- a/arch/csr/Zihpm/mhpmevent31h.yaml +++ b/arch/csr/Zihpm/mhpmevent31h.yaml @@ -4,140 +4,142 @@ -mhpmevent31h: - long_name: Machine Hardware Performance Counter 31 Control, High half - address: 0x73F - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent31`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent31h +long_name: Machine Hardware Performance Counter 31 Control, High half +address: 0x73F +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent31`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent31.OF - description: | - Alias of mhpmevent31.OF. - type(): | - if (HPM_COUNTER_EN[31]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[31]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent31.MINH - description: | - Alias of mhpmevent31.MINH. - type(): | - if (HPM_COUNTER_EN[31]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[31]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent31.SINH - description: | - Alias of mhpmevent31.SINH. - type(): | - if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent31.UINH - description: | - Alias of mhpmevent31.UINH. - type(): | - if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent31.VSINH - description: | - Alias of mhpmevent31.VSINH. - type(): | - if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent31.VUINH - description: | - Alias of mhpmevent31.VUINH. - type(): | - if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter31`. - alias: mhpmevent31.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[31]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[31]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent31.OF + description: | + Alias of mhpmevent31.OF. + type(): | + if (HPM_COUNTER_EN[31]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[31]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent31.MINH + description: | + Alias of mhpmevent31.MINH. + type(): | + if (HPM_COUNTER_EN[31]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[31]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent31.SINH + description: | + Alias of mhpmevent31.SINH. + type(): | + if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent31.UINH + description: | + Alias of mhpmevent31.UINH. + type(): | + if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent31.VSINH + description: | + Alias of mhpmevent31.VSINH. + type(): | + if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent31.VUINH + description: | + Alias of mhpmevent31.VUINH. + type(): | + if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[31]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter31`. + alias: mhpmevent31.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[31]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[31]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent3h.yaml b/arch/csr/Zihpm/mhpmevent3h.yaml index 159319fe5..a2e4999af 100644 --- a/arch/csr/Zihpm/mhpmevent3h.yaml +++ b/arch/csr/Zihpm/mhpmevent3h.yaml @@ -4,140 +4,142 @@ -mhpmevent3h: - long_name: Machine Hardware Performance Counter 3 Control, High half - address: 0x723 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent3`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent3h +long_name: Machine Hardware Performance Counter 3 Control, High half +address: 0x723 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent3`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent3.OF - description: | - Alias of mhpmevent3.OF. - type(): | - if (HPM_COUNTER_EN[3]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[3]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent3.MINH - description: | - Alias of mhpmevent3.MINH. - type(): | - if (HPM_COUNTER_EN[3]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[3]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent3.SINH - description: | - Alias of mhpmevent3.SINH. - type(): | - if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent3.UINH - description: | - Alias of mhpmevent3.UINH. - type(): | - if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent3.VSINH - description: | - Alias of mhpmevent3.VSINH. - type(): | - if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent3.VUINH - description: | - Alias of mhpmevent3.VUINH. - type(): | - if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter3`. - alias: mhpmevent3.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[3]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[3]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent3.OF + description: | + Alias of mhpmevent3.OF. + type(): | + if (HPM_COUNTER_EN[3]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[3]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent3.MINH + description: | + Alias of mhpmevent3.MINH. + type(): | + if (HPM_COUNTER_EN[3]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[3]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent3.SINH + description: | + Alias of mhpmevent3.SINH. + type(): | + if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent3.UINH + description: | + Alias of mhpmevent3.UINH. + type(): | + if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent3.VSINH + description: | + Alias of mhpmevent3.VSINH. + type(): | + if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent3.VUINH + description: | + Alias of mhpmevent3.VUINH. + type(): | + if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[3]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter3`. + alias: mhpmevent3.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[3]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[3]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent4.yaml b/arch/csr/Zihpm/mhpmevent4.yaml index 8b75bca85..62e60497f 100644 --- a/arch/csr/Zihpm/mhpmevent4.yaml +++ b/arch/csr/Zihpm/mhpmevent4.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent4: - long_name: Machine Hardware Performance Counter 4 Control - address: 0x324 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent4 +long_name: Machine Hardware Performance Counter 4 Control +address: 0x324 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter4 overflows. - type(): | - if (HPM_COUNTER_EN[4]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[4]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter4 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[4]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[4]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter4 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[4] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[4] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter4 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[4] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[4] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter4 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[4] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter4 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[4] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter4`. - type(): | - if (HPM_COUNTER_EN[4]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[4]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter4 overflows. + type(): | + if (HPM_COUNTER_EN[4]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[4]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter4 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[4]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[4]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter4 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[4] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[4] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter4 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[4] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[4] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter4 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[4] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter4 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[4] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter4`. + type(): | + if (HPM_COUNTER_EN[4]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[4]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent4h.yaml b/arch/csr/Zihpm/mhpmevent4h.yaml index 3bfa42f66..9981a53d1 100644 --- a/arch/csr/Zihpm/mhpmevent4h.yaml +++ b/arch/csr/Zihpm/mhpmevent4h.yaml @@ -4,140 +4,142 @@ -mhpmevent4h: - long_name: Machine Hardware Performance Counter 4 Control, High half - address: 0x724 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent4`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent4h +long_name: Machine Hardware Performance Counter 4 Control, High half +address: 0x724 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent4`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent4.OF - description: | - Alias of mhpmevent4.OF. - type(): | - if (HPM_COUNTER_EN[4]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[4]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent4.MINH - description: | - Alias of mhpmevent4.MINH. - type(): | - if (HPM_COUNTER_EN[4]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[4]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent4.SINH - description: | - Alias of mhpmevent4.SINH. - type(): | - if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent4.UINH - description: | - Alias of mhpmevent4.UINH. - type(): | - if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent4.VSINH - description: | - Alias of mhpmevent4.VSINH. - type(): | - if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent4.VUINH - description: | - Alias of mhpmevent4.VUINH. - type(): | - if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter4`. - alias: mhpmevent4.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[4]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[4]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent4.OF + description: | + Alias of mhpmevent4.OF. + type(): | + if (HPM_COUNTER_EN[4]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[4]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent4.MINH + description: | + Alias of mhpmevent4.MINH. + type(): | + if (HPM_COUNTER_EN[4]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[4]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent4.SINH + description: | + Alias of mhpmevent4.SINH. + type(): | + if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent4.UINH + description: | + Alias of mhpmevent4.UINH. + type(): | + if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent4.VSINH + description: | + Alias of mhpmevent4.VSINH. + type(): | + if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent4.VUINH + description: | + Alias of mhpmevent4.VUINH. + type(): | + if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[4]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter4`. + alias: mhpmevent4.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[4]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[4]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent5.yaml b/arch/csr/Zihpm/mhpmevent5.yaml index 1599f5ea5..6f84cbb99 100644 --- a/arch/csr/Zihpm/mhpmevent5.yaml +++ b/arch/csr/Zihpm/mhpmevent5.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent5: - long_name: Machine Hardware Performance Counter 5 Control - address: 0x325 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent5 +long_name: Machine Hardware Performance Counter 5 Control +address: 0x325 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter5 overflows. - type(): | - if (HPM_COUNTER_EN[5]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[5]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter5 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[5]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[5]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter5 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[5] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[5] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter5 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[5] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[5] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter5 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[5] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter5 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[5] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter5`. - type(): | - if (HPM_COUNTER_EN[5]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[5]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter5 overflows. + type(): | + if (HPM_COUNTER_EN[5]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[5]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter5 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[5]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[5]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter5 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[5] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[5] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter5 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[5] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[5] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter5 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[5] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter5 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[5] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter5`. + type(): | + if (HPM_COUNTER_EN[5]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[5]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent5h.yaml b/arch/csr/Zihpm/mhpmevent5h.yaml index f9e4d66d0..9194e4794 100644 --- a/arch/csr/Zihpm/mhpmevent5h.yaml +++ b/arch/csr/Zihpm/mhpmevent5h.yaml @@ -4,140 +4,142 @@ -mhpmevent5h: - long_name: Machine Hardware Performance Counter 5 Control, High half - address: 0x725 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent5`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent5h +long_name: Machine Hardware Performance Counter 5 Control, High half +address: 0x725 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent5`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent5.OF - description: | - Alias of mhpmevent5.OF. - type(): | - if (HPM_COUNTER_EN[5]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[5]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent5.MINH - description: | - Alias of mhpmevent5.MINH. - type(): | - if (HPM_COUNTER_EN[5]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[5]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent5.SINH - description: | - Alias of mhpmevent5.SINH. - type(): | - if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent5.UINH - description: | - Alias of mhpmevent5.UINH. - type(): | - if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent5.VSINH - description: | - Alias of mhpmevent5.VSINH. - type(): | - if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent5.VUINH - description: | - Alias of mhpmevent5.VUINH. - type(): | - if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter5`. - alias: mhpmevent5.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[5]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[5]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent5.OF + description: | + Alias of mhpmevent5.OF. + type(): | + if (HPM_COUNTER_EN[5]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[5]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent5.MINH + description: | + Alias of mhpmevent5.MINH. + type(): | + if (HPM_COUNTER_EN[5]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[5]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent5.SINH + description: | + Alias of mhpmevent5.SINH. + type(): | + if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent5.UINH + description: | + Alias of mhpmevent5.UINH. + type(): | + if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent5.VSINH + description: | + Alias of mhpmevent5.VSINH. + type(): | + if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent5.VUINH + description: | + Alias of mhpmevent5.VUINH. + type(): | + if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[5]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter5`. + alias: mhpmevent5.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[5]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[5]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent6.yaml b/arch/csr/Zihpm/mhpmevent6.yaml index f5f482c43..d60f46635 100644 --- a/arch/csr/Zihpm/mhpmevent6.yaml +++ b/arch/csr/Zihpm/mhpmevent6.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent6: - long_name: Machine Hardware Performance Counter 6 Control - address: 0x326 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent6 +long_name: Machine Hardware Performance Counter 6 Control +address: 0x326 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter6 overflows. - type(): | - if (HPM_COUNTER_EN[6]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[6]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter6 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[6]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[6]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter6 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[6] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[6] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter6 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[6] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[6] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter6 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[6] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter6 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[6] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter6`. - type(): | - if (HPM_COUNTER_EN[6]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[6]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter6 overflows. + type(): | + if (HPM_COUNTER_EN[6]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[6]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter6 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[6]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[6]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter6 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[6] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[6] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter6 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[6] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[6] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter6 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[6] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter6 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[6] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter6`. + type(): | + if (HPM_COUNTER_EN[6]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[6]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent6h.yaml b/arch/csr/Zihpm/mhpmevent6h.yaml index 64d1e1e26..4bcfb4141 100644 --- a/arch/csr/Zihpm/mhpmevent6h.yaml +++ b/arch/csr/Zihpm/mhpmevent6h.yaml @@ -4,140 +4,142 @@ -mhpmevent6h: - long_name: Machine Hardware Performance Counter 6 Control, High half - address: 0x726 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent6`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent6h +long_name: Machine Hardware Performance Counter 6 Control, High half +address: 0x726 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent6`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent6.OF - description: | - Alias of mhpmevent6.OF. - type(): | - if (HPM_COUNTER_EN[6]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[6]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent6.MINH - description: | - Alias of mhpmevent6.MINH. - type(): | - if (HPM_COUNTER_EN[6]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[6]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent6.SINH - description: | - Alias of mhpmevent6.SINH. - type(): | - if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent6.UINH - description: | - Alias of mhpmevent6.UINH. - type(): | - if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent6.VSINH - description: | - Alias of mhpmevent6.VSINH. - type(): | - if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent6.VUINH - description: | - Alias of mhpmevent6.VUINH. - type(): | - if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter6`. - alias: mhpmevent6.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[6]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[6]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent6.OF + description: | + Alias of mhpmevent6.OF. + type(): | + if (HPM_COUNTER_EN[6]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[6]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent6.MINH + description: | + Alias of mhpmevent6.MINH. + type(): | + if (HPM_COUNTER_EN[6]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[6]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent6.SINH + description: | + Alias of mhpmevent6.SINH. + type(): | + if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent6.UINH + description: | + Alias of mhpmevent6.UINH. + type(): | + if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent6.VSINH + description: | + Alias of mhpmevent6.VSINH. + type(): | + if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent6.VUINH + description: | + Alias of mhpmevent6.VUINH. + type(): | + if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[6]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter6`. + alias: mhpmevent6.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[6]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[6]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent7.yaml b/arch/csr/Zihpm/mhpmevent7.yaml index eb5093137..a439e216e 100644 --- a/arch/csr/Zihpm/mhpmevent7.yaml +++ b/arch/csr/Zihpm/mhpmevent7.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent7: - long_name: Machine Hardware Performance Counter 7 Control - address: 0x327 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent7 +long_name: Machine Hardware Performance Counter 7 Control +address: 0x327 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter7 overflows. - type(): | - if (HPM_COUNTER_EN[7]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[7]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter7 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[7]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[7]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter7 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[7] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[7] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter7 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[7] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[7] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter7 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[7] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter7 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[7] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter7`. - type(): | - if (HPM_COUNTER_EN[7]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[7]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter7 overflows. + type(): | + if (HPM_COUNTER_EN[7]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[7]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter7 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[7]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[7]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter7 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[7] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[7] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter7 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[7] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[7] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter7 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[7] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter7 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[7] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter7`. + type(): | + if (HPM_COUNTER_EN[7]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[7]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent7h.yaml b/arch/csr/Zihpm/mhpmevent7h.yaml index f53788b68..a35879b13 100644 --- a/arch/csr/Zihpm/mhpmevent7h.yaml +++ b/arch/csr/Zihpm/mhpmevent7h.yaml @@ -4,140 +4,142 @@ -mhpmevent7h: - long_name: Machine Hardware Performance Counter 7 Control, High half - address: 0x727 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent7`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent7h +long_name: Machine Hardware Performance Counter 7 Control, High half +address: 0x727 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent7`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent7.OF - description: | - Alias of mhpmevent7.OF. - type(): | - if (HPM_COUNTER_EN[7]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[7]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent7.MINH - description: | - Alias of mhpmevent7.MINH. - type(): | - if (HPM_COUNTER_EN[7]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[7]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent7.SINH - description: | - Alias of mhpmevent7.SINH. - type(): | - if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent7.UINH - description: | - Alias of mhpmevent7.UINH. - type(): | - if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent7.VSINH - description: | - Alias of mhpmevent7.VSINH. - type(): | - if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent7.VUINH - description: | - Alias of mhpmevent7.VUINH. - type(): | - if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter7`. - alias: mhpmevent7.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[7]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[7]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent7.OF + description: | + Alias of mhpmevent7.OF. + type(): | + if (HPM_COUNTER_EN[7]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[7]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent7.MINH + description: | + Alias of mhpmevent7.MINH. + type(): | + if (HPM_COUNTER_EN[7]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[7]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent7.SINH + description: | + Alias of mhpmevent7.SINH. + type(): | + if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent7.UINH + description: | + Alias of mhpmevent7.UINH. + type(): | + if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent7.VSINH + description: | + Alias of mhpmevent7.VSINH. + type(): | + if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent7.VUINH + description: | + Alias of mhpmevent7.VUINH. + type(): | + if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[7]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter7`. + alias: mhpmevent7.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[7]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[7]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent8.yaml b/arch/csr/Zihpm/mhpmevent8.yaml index 106928a0a..2b7d07127 100644 --- a/arch/csr/Zihpm/mhpmevent8.yaml +++ b/arch/csr/Zihpm/mhpmevent8.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent8: - long_name: Machine Hardware Performance Counter 8 Control - address: 0x328 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent8 +long_name: Machine Hardware Performance Counter 8 Control +address: 0x328 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter8 overflows. - type(): | - if (HPM_COUNTER_EN[8]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[8]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter8 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[8]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[8]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter8 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[8] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[8] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter8 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[8] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[8] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter8 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[8] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter8 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[8] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter8`. - type(): | - if (HPM_COUNTER_EN[8]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[8]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter8 overflows. + type(): | + if (HPM_COUNTER_EN[8]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[8]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter8 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[8]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[8]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter8 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[8] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[8] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter8 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[8] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[8] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter8 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[8] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter8 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[8] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter8`. + type(): | + if (HPM_COUNTER_EN[8]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[8]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent8h.yaml b/arch/csr/Zihpm/mhpmevent8h.yaml index 8ed03bd98..c3abcd162 100644 --- a/arch/csr/Zihpm/mhpmevent8h.yaml +++ b/arch/csr/Zihpm/mhpmevent8h.yaml @@ -4,140 +4,142 @@ -mhpmevent8h: - long_name: Machine Hardware Performance Counter 8 Control, High half - address: 0x728 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent8`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent8h +long_name: Machine Hardware Performance Counter 8 Control, High half +address: 0x728 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent8`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent8.OF - description: | - Alias of mhpmevent8.OF. - type(): | - if (HPM_COUNTER_EN[8]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[8]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent8.MINH - description: | - Alias of mhpmevent8.MINH. - type(): | - if (HPM_COUNTER_EN[8]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[8]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent8.SINH - description: | - Alias of mhpmevent8.SINH. - type(): | - if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent8.UINH - description: | - Alias of mhpmevent8.UINH. - type(): | - if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent8.VSINH - description: | - Alias of mhpmevent8.VSINH. - type(): | - if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent8.VUINH - description: | - Alias of mhpmevent8.VUINH. - type(): | - if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter8`. - alias: mhpmevent8.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[8]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[8]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent8.OF + description: | + Alias of mhpmevent8.OF. + type(): | + if (HPM_COUNTER_EN[8]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[8]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent8.MINH + description: | + Alias of mhpmevent8.MINH. + type(): | + if (HPM_COUNTER_EN[8]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[8]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent8.SINH + description: | + Alias of mhpmevent8.SINH. + type(): | + if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent8.UINH + description: | + Alias of mhpmevent8.UINH. + type(): | + if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent8.VSINH + description: | + Alias of mhpmevent8.VSINH. + type(): | + if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent8.VUINH + description: | + Alias of mhpmevent8.VUINH. + type(): | + if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[8]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter8`. + alias: mhpmevent8.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[8]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[8]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmevent9.yaml b/arch/csr/Zihpm/mhpmevent9.yaml index b3227c6b7..821178e99 100644 --- a/arch/csr/Zihpm/mhpmevent9.yaml +++ b/arch/csr/Zihpm/mhpmevent9.yaml @@ -5,140 +5,142 @@ # yaml-language-server: $schema=../../../schemas/csr_schema.json -mhpmevent9: - long_name: Machine Hardware Performance Counter 9 Control - address: 0x329 - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: mhpmevent9 +long_name: Machine Hardware Performance Counter 9 Control +address: 0x329 +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <% if ext?(:Sscofpmf) %> and overflow/filtering control<% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter9 overflows. - type(): | - if (HPM_COUNTER_EN[9]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[9]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter9 does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[9]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[9]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter9 does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[9] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[9] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter9 does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[9] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[9] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter9 does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[9] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter9 does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[9] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter9`. - type(): | - if (HPM_COUNTER_EN[9]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[9]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter9 overflows. + type(): | + if (HPM_COUNTER_EN[9]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[9]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter9 does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[9]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[9]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter9 does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[9] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[9] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter9 does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[9] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[9] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter9 does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[9] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter9 does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[9] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter9`. + type(): | + if (HPM_COUNTER_EN[9]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[9]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmevent9h.yaml b/arch/csr/Zihpm/mhpmevent9h.yaml index 7ffe84d68..90ebe2e27 100644 --- a/arch/csr/Zihpm/mhpmevent9h.yaml +++ b/arch/csr/Zihpm/mhpmevent9h.yaml @@ -4,140 +4,142 @@ -mhpmevent9h: - long_name: Machine Hardware Performance Counter 9 Control, High half - address: 0x729 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent9`[63:32]. +$schema: csr_schema.json# +kind: csr +name: mhpmevent9h +long_name: Machine Hardware Performance Counter 9 Control, High half +address: 0x729 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent9`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent9.OF - description: | - Alias of mhpmevent9.OF. - type(): | - if (HPM_COUNTER_EN[9]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[9]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent9.MINH - description: | - Alias of mhpmevent9.MINH. - type(): | - if (HPM_COUNTER_EN[9]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[9]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent9.SINH - description: | - Alias of mhpmevent9.SINH. - type(): | - if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent9.UINH - description: | - Alias of mhpmevent9.UINH. - type(): | - if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent9.VSINH - description: | - Alias of mhpmevent9.VSINH. - type(): | - if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent9.VUINH - description: | - Alias of mhpmevent9.VUINH. - type(): | - if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter9`. - alias: mhpmevent9.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[9]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[9]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent9.OF + description: | + Alias of mhpmevent9.OF. + type(): | + if (HPM_COUNTER_EN[9]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[9]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent9.MINH + description: | + Alias of mhpmevent9.MINH. + type(): | + if (HPM_COUNTER_EN[9]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[9]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent9.SINH + description: | + Alias of mhpmevent9.SINH. + type(): | + if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent9.UINH + description: | + Alias of mhpmevent9.UINH. + type(): | + if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent9.VSINH + description: | + Alias of mhpmevent9.VSINH. + type(): | + if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent9.VUINH + description: | + Alias of mhpmevent9.VUINH. + type(): | + if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[9]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter9`. + alias: mhpmevent9.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[9]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[9]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/Zihpm/mhpmeventN.layout b/arch/csr/Zihpm/mhpmeventN.layout index 31b59fd72..4324c11a1 100644 --- a/arch/csr/Zihpm/mhpmeventN.layout +++ b/arch/csr/Zihpm/mhpmeventN.layout @@ -3,140 +3,142 @@ <%- raise "'hpm_num' must be defined" if hpm_num.nil? -%> -<%= "mhpmevent#{hpm_num}" %>: - long_name: Machine Hardware Performance Counter <%= hpm_num %> Control - address: <%= "0x" + (0x320 + hpm_num).to_s(16).upcase %> - priv_mode: M - length: 64 - description: | - Programmable hardware performance counter event selector - <%% if ext?(:Sscofpmf) %> and overflow/filtering control<%% end %> - definedBy: Smhpm - fields: - OF: - location: 63 - description: | - Overflow status and interrupt disable. +$schema: csr_schema.json# +kind: csr +name: <%= "mhpmevent#{hpm_num}" %> +long_name: Machine Hardware Performance Counter <%= hpm_num %> Control +address: <%= "0x" + (0x320 + hpm_num).to_s(16).upcase %> +priv_mode: M +length: 64 +description: | + Programmable hardware performance counter event selector + <%% if ext?(:Sscofpmf) %> and overflow/filtering control<%% end %> +definedBy: Smhpm +fields: + OF: + location: 63 + description: | + Overflow status and interrupt disable. - The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by - software. Since hpmcounter values are unsigned values, overflow is defined as unsigned - overflow of the implemented counter bits. + The OF bit is set when the corresponding hpmcounter overflows, and remains set until written by + software. Since hpmcounter values are unsigned values, overflow is defined as unsigned + overflow of the implemented counter bits. - The OF bit is sticky; it stays set until explictly cleared by a CSR write. + The OF bit is sticky; it stays set until explictly cleared by a CSR write. - A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and - mhpmcounter<%= hpm_num %> overflows. - type(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 62 - description: When set, mhpmcounter<%= hpm_num %> does not increment while the hart in operating in M-mode. - type(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 61 - description: When set, mhpmcounter<%= hpm_num %> does not increment while the hart in operating in (H)S-mode. - type(): | - if (HPM_COUNTER_EN[<%= hpm_num %>] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[<%= hpm_num %>] && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 60 - description: When set, mhpmcounter<%= hpm_num %> does not increment while the hart in operating in U-mode. - type(): | - if (HPM_COUNTER_EN[<%= hpm_num %>] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[<%= hpm_num %>] && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 59 - description: When set, mhpmcounter<%= hpm_num %> does not increment while the hart in operating in VS-mode. - type(): | - if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[<%= hpm_num %>] && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 58 - description: When set, mhpmcounter<%= hpm_num %> does not increment while the hart in operating in VU-mode. - type(): | - if (HPM_COUNTER_EN[<%= hpm_num %>] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 57-0 - description: Event selector for performance counter `mhpmcounter<%= hpm_num %>`. - type(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { - return csr_value.EVENT; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + A Local Counter Overflow Interrupt (LCOFI) is generated when OF is clear and + mhpmcounter<%= hpm_num %> overflows. + type(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 62 + description: When set, mhpmcounter<%= hpm_num %> does not increment while the hart in operating in M-mode. + type(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 61 + description: When set, mhpmcounter<%= hpm_num %> does not increment while the hart in operating in (H)S-mode. + type(): | + if (HPM_COUNTER_EN[<%= hpm_num %>] && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[<%= hpm_num %>] && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 60 + description: When set, mhpmcounter<%= hpm_num %> does not increment while the hart in operating in U-mode. + type(): | + if (HPM_COUNTER_EN[<%= hpm_num %>] && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[<%= hpm_num %>] && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 59 + description: When set, mhpmcounter<%= hpm_num %> does not increment while the hart in operating in VS-mode. + type(): | + if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[<%= hpm_num %>] && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 58 + description: When set, mhpmcounter<%= hpm_num %> does not increment while the hart in operating in VU-mode. + type(): | + if (HPM_COUNTER_EN[<%= hpm_num %>] && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 57-0 + description: Event selector for performance counter `mhpmcounter<%= hpm_num %>`. + type(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (ary_includes?<$array_size(HPM_EVENTS), 58>(HPM_EVENTS, csr_value.EVENT)) { + return csr_value.EVENT; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } diff --git a/arch/csr/Zihpm/mhpmeventNh.layout b/arch/csr/Zihpm/mhpmeventNh.layout index db7064833..deaa0116a 100644 --- a/arch/csr/Zihpm/mhpmeventNh.layout +++ b/arch/csr/Zihpm/mhpmeventNh.layout @@ -2,140 +2,142 @@ <%- raise "'hpm_num' must be defined" if hpm_num.nil? -%> -<%= "mhpmevent#{hpm_num}h" %>: - long_name: Machine Hardware Performance Counter <%= hpm_num %> Control, High half - address: 0x<%= (0x720 + hpm_num).to_s(16).upcase %> - priv_mode: M - length: 32 - base: 32 - description: | - Alias of `mhpmevent<%= hpm_num %>`[63:32]. +$schema: csr_schema.json# +kind: csr +name: <%= "mhpmevent#{hpm_num}h" %> +long_name: Machine Hardware Performance Counter <%= hpm_num %> Control, High half +address: 0x<%= (0x720 + hpm_num).to_s(16).upcase %> +priv_mode: M +length: 32 +base: 32 +description: | + Alias of `mhpmevent<%= hpm_num %>`[63:32]. - Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper - 32-bits of `mhpmevent#{hpm_num}`. - definedBy: Sscofpmf - fields: - OF: - location: 31 - alias: mhpmevent<%= hpm_num %>.OF - description: | - Alias of mhpmevent<%= hpm_num %>.OF. - type(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return CsrFieldType::RWH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - MINH: - location: 30 - alias: mhpmevent<%= hpm_num %>.MINH - description: | - Alias of mhpmevent<%= hpm_num %>.MINH. - type(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - SINH: - location: 29 - alias: mhpmevent<%= hpm_num %>.SINH - description: | - Alias of mhpmevent<%= hpm_num %>.SINH. - type(): | - if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - UINH: - location: 28 - alias: mhpmevent<%= hpm_num %>.UINH - description: | - Alias of mhpmevent<%= hpm_num %>.UINH. - type(): | - if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VSINH: - location: 27 - alias: mhpmevent<%= hpm_num %>.VSINH - description: | - Alias of mhpmevent<%= hpm_num %>.VSINH. - type(): | - if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - VUINH: - location: 26 - alias: mhpmevent<%= hpm_num %>.VUINH - description: | - Alias of mhpmevent<%= hpm_num %>.VUINH. - type(): | - if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::H)) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - definedBy: Sscofpmf - EVENT: - location: 25-0 - description: High part of event selector for performance counter `mhpmcounter<%= hpm_num %>`. - alias: mhpmevent<%= hpm_num %>.EVENT[57:32] - type(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (HPM_COUNTER_EN[<%= hpm_num %>]) { - return UNDEFINED_LEGAL; - } else { - return 0; - } + Introduced with the `Sscofpmf` extension. Prior to that, there was no way to access the upper + 32-bits of `mhpmevent#{hpm_num}`. +definedBy: Sscofpmf +fields: + OF: + location: 31 + alias: mhpmevent<%= hpm_num %>.OF + description: | + Alias of mhpmevent<%= hpm_num %>.OF. + type(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return CsrFieldType::RWH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + MINH: + location: 30 + alias: mhpmevent<%= hpm_num %>.MINH + description: | + Alias of mhpmevent<%= hpm_num %>.MINH. + type(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + SINH: + location: 29 + alias: mhpmevent<%= hpm_num %>.SINH + description: | + Alias of mhpmevent<%= hpm_num %>.SINH. + type(): | + if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::S) && (CSR[misa].S == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + UINH: + location: 28 + alias: mhpmevent<%= hpm_num %>.UINH + description: | + Alias of mhpmevent<%= hpm_num %>.UINH. + type(): | + if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::U) && (CSR[misa].U == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VSINH: + location: 27 + alias: mhpmevent<%= hpm_num %>.VSINH + description: | + Alias of mhpmevent<%= hpm_num %>.VSINH. + type(): | + if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + VUINH: + location: 26 + alias: mhpmevent<%= hpm_num %>.VUINH + description: | + Alias of mhpmevent<%= hpm_num %>.VUINH. + type(): | + if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::H) && (CSR[misa].H == 1'b1)) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if ((HPM_COUNTER_EN[<%= hpm_num %>]) && implemented?(ExtensionName::H)) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + definedBy: Sscofpmf + EVENT: + location: 25-0 + description: High part of event selector for performance counter `mhpmcounter<%= hpm_num %>`. + alias: mhpmevent<%= hpm_num %>.EVENT[57:32] + type(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (HPM_COUNTER_EN[<%= hpm_num %>]) { + return UNDEFINED_LEGAL; + } else { + return 0; + } diff --git a/arch/csr/cycle.yaml b/arch/csr/cycle.yaml index 81903c69f..50084c604 100644 --- a/arch/csr/cycle.yaml +++ b/arch/csr/cycle.yaml @@ -1,71 +1,73 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -cycle: - long_name: Cycle counter for RDCYCLE Instruction - address: 0xC00 - description: | - Alias for M-mode CSR `mcycle`. +$schema: "csr_schema.json#" +kind: csr +name: cycle +long_name: Cycle counter for RDCYCLE Instruction +address: 0xC00 +description: | + Alias for M-mode CSR `mcycle`. - Privilege mode access is controlled with `mcounteren.CY`, `scounteren.CY`, and `hcounteren.CY` as follows: + Privilege mode access is controlled with `mcounteren.CY`, `scounteren.CY`, and `hcounteren.CY` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.CY`# .2+h! [.rotate]#`scounteren.CY`# .2+h! [.rotate]#`hcounteren.CY`# - 4+^.>h! `cycle` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.CY`# .2+h! [.rotate]#`scounteren.CY`# .2+h! [.rotate]#`hcounteren.CY`# + 4+^.>h! `cycle` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Zicntr - fields: - COUNT: - location: 63-0 - alias: mcycle.COUNT - description: Alias of `mcycle.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Zicntr +fields: + COUNT: + location: 63-0 + alias: mcycle.COUNT + description: Alias of `mcycle.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].CY == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].CY == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].CY & CSR[scounteren].CY) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].CY == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].CY == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].CY == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].CY & CSR[scounteren].CY) == 1'b0) && (CSR[mcounteren].CY == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].CY == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].CY & CSR[scounteren].CY) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].CY == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].CY == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].CY == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].CY & CSR[scounteren].CY) == 1'b0) && (CSR[mcounteren].CY == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].CY == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - # since the counter may be shared among harts, reads must be handled - # as a builtin function - return read_mcycle(); + # since the counter may be shared among harts, reads must be handled + # as a builtin function + return read_mcycle(); diff --git a/arch/csr/cycleh.yaml b/arch/csr/cycleh.yaml index 9bdc67931..2c2f664d4 100644 --- a/arch/csr/cycleh.yaml +++ b/arch/csr/cycleh.yaml @@ -1,77 +1,79 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -cycleh: - long_name: High-half cycle counter for RDCYCLE Instruction - address: 0xC80 - base: 32 - description: | - Alias for M-mode CSR `mcycleh`. +$schema: "csr_schema.json#" +kind: csr +name: cycleh +long_name: High-half cycle counter for RDCYCLE Instruction +address: 0xC80 +base: 32 +description: | + Alias for M-mode CSR `mcycleh`. - Privilege mode access is controlled with `mcounteren.CY`, `scounteren.CY`, and `hcounteren.CY` as follows: + Privilege mode access is controlled with `mcounteren.CY`, `scounteren.CY`, and `hcounteren.CY` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.CY`# .2+h! [.rotate]#`scounteren.CY`# .2+h! [.rotate]#`hcounteren.CY`# - 4+^.>h! `cycle` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.CY`# .2+h! [.rotate]#`scounteren.CY`# .2+h! [.rotate]#`hcounteren.CY`# + 4+^.>h! `cycle` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 32 - definedBy: Zicntr - fields: - COUNT: - location: 31-0 - alias: mcycleh.COUNT[63:32] - description: Alias of `mcycleh.COUNT`. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # NOTE: The spec specifically says that reading cycleh when XLEN == 64 always causes - # IllegalInstruction exception even if it would otherwise be changed to a `VirtualInstruction - # exception. We don't have to explicitly check this here because it is already implied by - # the base constraint + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 32 +definedBy: Zicntr +fields: + COUNT: + location: 31-0 + alias: mcycleh.COUNT[63:32] + description: Alias of `mcycleh.COUNT`. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # NOTE: The spec specifically says that reading cycleh when XLEN == 64 always causes + # IllegalInstruction exception even if it would otherwise be changed to a `VirtualInstruction + # exception. We don't have to explicitly check this here because it is already implied by + # the base constraint - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].CY == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].CY == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].CY & CSR[scounteren].CY) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].CY == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].CY == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].CY == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].CY & CSR[scounteren].CY) == 1'b0) && (CSR[mcounteren].CY == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].CY == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].CY & CSR[scounteren].CY) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].CY == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].CY == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].CY == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].CY & CSR[scounteren].CY) == 1'b0) && (CSR[mcounteren].CY == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].CY == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - # since the counter may be shared among harts, reads must be handled - # as a builtin function - return read_mcycle()[63:32]; + # since the counter may be shared among harts, reads must be handled + # as a builtin function + return read_mcycle()[63:32]; diff --git a/arch/csr/hedeleg.yaml b/arch/csr/hedeleg.yaml index fc6d01b08..cfd5f7f63 100644 --- a/arch/csr/hedeleg.yaml +++ b/arch/csr/hedeleg.yaml @@ -1,235 +1,237 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -hedeleg: - long_name: Hypervisor Exception Delegation - address: 0x602 - priv_mode: S - length: 64 - description: | - Controls exception delegation from HS-mode to VS-mode. - - By default, all traps at any privilege level are handled in M-mode, though M-mode usually uses - the `medeleg` and `mideleg` CSRs to delegate some traps to HS-mode. The `hedeleg` and `hideleg` - CSRs allow these traps to be further delegated to a VS-mode guest; their layout is the same as - `medeleg` and `mideleg`. - - A synchronous trap that has been delegated to HS-mode (using `medeleg`) - is further delegated to VS-mode if V=1 before the trap and the - corresponding `hedeleg` bit is set. Each bit of `hedeleg` shall be - either writable or read-only zero. Many bits of `hedeleg` are required - specifically to be writable or zero. Bit 0, corresponding to - instruction address misaligned exceptions, must be writable if - IALIGN=32. - - [NOTE] - ==== - Requiring that certain bits of `hedeleg` be writable reduces some of the - burden on a hypervisor to handle variations of implementation. - ==== - - When XLEN=32, `hedelegh` is a 32-bit read/write register - that aliases bits 63:32 of `hedeleg`. - Register `hedelegh` does not exist when XLEN=64. - - definedBy: H - fields: - IAM: - location: 0 - description: | - *Instruction Address Misaligned* - - Controls delegation of Instruction Address Misaligned exceptions to VS-mode. - - See `medeleg.IAM` for details. - type: RW - reset_value: UNDEFINED_LEGAL - IAF: - location: 1 - description: | - *Instruction Access Fault* - - Controls delegation of Instruction Access Fault exceptions to VS-mode. - - See `medeleg.IAF` for details. - - type: RW - reset_value: UNDEFINED_LEGAL - II: - location: 2 - description: | - *Illegal Instruction* - - Controls delegation of Illegal Instruction exceptions to VS-mode. - - See `medeleg.II` for details. - - type: RW - reset_value: UNDEFINED_LEGAL - B: - location: 3 - description: | - *Breakpoint* - - Controls delegation of Breakpoint exceptions to VS-mode. - - See `medeleg.B` for details. - type: RW - reset_value: UNDEFINED_LEGAL - LAM: - location: 4 - description: | - *Load Address Misaligned* - - Controls delegation of Load Address Misaligned exceptions to VS-mode. - - See `medeleg.LAM` for details. - type: RW - reset_value: UNDEFINED_LEGAL - LAF: - location: 5 - description: | - *Load Access Fault* - - Controls delegation of Load Access Fault exceptions to VS-mode. - - See `medeleg.LAF` for details. - type: RW - reset_value: UNDEFINED_LEGAL - SAM: - location: 6 - description: | - *Store/AMO Address Misaligned* - - Controls delegation of Store/AMO Address Misaligned exceptions to VS-mode. - - See `medeleg.SAM` for details. - type: RW - reset_value: UNDEFINED_LEGAL - SAF: - location: 7 - description: | - *Store/AMO Access Fault* - - Controls delegation of Store/AMO Access Fault exceptions to VS-mode. - - See `medeleg.SAF` for details. - type: RW - reset_value: UNDEFINED_LEGAL - EU: - location: 8 - description: | - *Environment Call from VU-mode* - - Controls delegation of Enviornment Call from VU-mode exceptions to VS-mode. - - See `medeleg.EU` for details. - - type: RW - reset_value: UNDEFINED_LEGAL - ES: - location: 9 - description: | - *Environment Call from HS-mode* - - Enviornment Call from HS-mode exceptions _cannot be delegated to VS-mode_, - so this field is read-only 0. - - See `medeleg.ES` for details. - type: RO - reset_value: 0 - EVS: - location: 10 - description: | - *Environment Call from VS-mode* - - Enviornment Call from VS-mode exceptions _cannot be delegated to VS-mode_, - so this field is read-only 0. - - See `medeleg.EVS` for details. - type: RO - reset_value: 0 - EM: - location: 11 - description: | - *Environment Call from M-mode* - - Enviornment Call from M-mode exceptions _cannot be delegated to VS-mode_, - so this field is read-only 0. - - See `medeleg.EM` for details. - type: RO - reset_value: 0 - IPF: - location: 12 - description: | - *Instruction Page Fault* - - Controls delegation of Instruction Page Fault exceptions to VS-mode. - - See `medeleg.IPF` for details. - type: RW - reset_value: UNDEFINED_LEGAL - LPF: - location: 13 - description: | - *Load Page Fault* - - Controls delegation of Load Page Fault exceptions to VS-mode. - - See `medeleg.LPF` for details. - type: RW - reset_value: UNDEFINED_LEGAL - SPF: - location: 15 - description: | - *Store/AMO Page Fault* - - Controls delegation of Store/AMO Page Fault exceptions to VS-mode. - - See `medeleg.SPF` for details. - type: RW - reset_value: UNDEFINED_LEGAL - IGPF: - location: 20 - description: | - *Instruction Guest Page Fault* - - Instruction Guest Page Fault exceptions _cannot be delegated to VS-mode_, - so this field is read-only 0. - - See `medeleg.IGPF` for details. - type: RO - reset_value: 0 - LGPF: - location: 21 - description: | - *Load Guest Page Fault* - - Load Guest Page Fault exceptions _cannot be delegated to VS-mode_, - so this field is read-only 0. - - See `medeleg.LGPF` for details. - type: RO - reset_value: 0 - VI: - location: 22 - description: | - *Virtual Instruction* - - Virtual Instruction exceptions _cannot be delegated to VS-mode_, - so this field is read-only 0. - - See `medeleg.VI` for details. - type: RO - reset_value: 0 - SGPF: - location: 23 - description: | - *Store/AMO Guest Page Fault* - - Store/AMO Guest Page Fault exceptions _cannot be delegated to VS-mode_, - so this field is read-only 0. - - See `medeleg.SGPF` for details. - type: RO - reset_value: 0 +$schema: "csr_schema.json#" +kind: csr +name: hedeleg +long_name: Hypervisor Exception Delegation +address: 0x602 +priv_mode: S +length: 64 +description: | + Controls exception delegation from HS-mode to VS-mode. + + By default, all traps at any privilege level are handled in M-mode, though M-mode usually uses + the `medeleg` and `mideleg` CSRs to delegate some traps to HS-mode. The `hedeleg` and `hideleg` + CSRs allow these traps to be further delegated to a VS-mode guest; their layout is the same as + `medeleg` and `mideleg`. + + A synchronous trap that has been delegated to HS-mode (using `medeleg`) + is further delegated to VS-mode if V=1 before the trap and the + corresponding `hedeleg` bit is set. Each bit of `hedeleg` shall be + either writable or read-only zero. Many bits of `hedeleg` are required + specifically to be writable or zero. Bit 0, corresponding to + instruction address misaligned exceptions, must be writable if + IALIGN=32. + + [NOTE] + ==== + Requiring that certain bits of `hedeleg` be writable reduces some of the + burden on a hypervisor to handle variations of implementation. + ==== + + When XLEN=32, `hedelegh` is a 32-bit read/write register + that aliases bits 63:32 of `hedeleg`. + Register `hedelegh` does not exist when XLEN=64. + +definedBy: H +fields: + IAM: + location: 0 + description: | + *Instruction Address Misaligned* + + Controls delegation of Instruction Address Misaligned exceptions to VS-mode. + + See `medeleg.IAM` for details. + type: RW + reset_value: UNDEFINED_LEGAL + IAF: + location: 1 + description: | + *Instruction Access Fault* + + Controls delegation of Instruction Access Fault exceptions to VS-mode. + + See `medeleg.IAF` for details. + + type: RW + reset_value: UNDEFINED_LEGAL + II: + location: 2 + description: | + *Illegal Instruction* + + Controls delegation of Illegal Instruction exceptions to VS-mode. + + See `medeleg.II` for details. + + type: RW + reset_value: UNDEFINED_LEGAL + B: + location: 3 + description: | + *Breakpoint* + + Controls delegation of Breakpoint exceptions to VS-mode. + + See `medeleg.B` for details. + type: RW + reset_value: UNDEFINED_LEGAL + LAM: + location: 4 + description: | + *Load Address Misaligned* + + Controls delegation of Load Address Misaligned exceptions to VS-mode. + + See `medeleg.LAM` for details. + type: RW + reset_value: UNDEFINED_LEGAL + LAF: + location: 5 + description: | + *Load Access Fault* + + Controls delegation of Load Access Fault exceptions to VS-mode. + + See `medeleg.LAF` for details. + type: RW + reset_value: UNDEFINED_LEGAL + SAM: + location: 6 + description: | + *Store/AMO Address Misaligned* + + Controls delegation of Store/AMO Address Misaligned exceptions to VS-mode. + + See `medeleg.SAM` for details. + type: RW + reset_value: UNDEFINED_LEGAL + SAF: + location: 7 + description: | + *Store/AMO Access Fault* + + Controls delegation of Store/AMO Access Fault exceptions to VS-mode. + + See `medeleg.SAF` for details. + type: RW + reset_value: UNDEFINED_LEGAL + EU: + location: 8 + description: | + *Environment Call from VU-mode* + + Controls delegation of Enviornment Call from VU-mode exceptions to VS-mode. + + See `medeleg.EU` for details. + + type: RW + reset_value: UNDEFINED_LEGAL + ES: + location: 9 + description: | + *Environment Call from HS-mode* + + Enviornment Call from HS-mode exceptions _cannot be delegated to VS-mode_, + so this field is read-only 0. + + See `medeleg.ES` for details. + type: RO + reset_value: 0 + EVS: + location: 10 + description: | + *Environment Call from VS-mode* + + Enviornment Call from VS-mode exceptions _cannot be delegated to VS-mode_, + so this field is read-only 0. + + See `medeleg.EVS` for details. + type: RO + reset_value: 0 + EM: + location: 11 + description: | + *Environment Call from M-mode* + + Enviornment Call from M-mode exceptions _cannot be delegated to VS-mode_, + so this field is read-only 0. + + See `medeleg.EM` for details. + type: RO + reset_value: 0 + IPF: + location: 12 + description: | + *Instruction Page Fault* + + Controls delegation of Instruction Page Fault exceptions to VS-mode. + + See `medeleg.IPF` for details. + type: RW + reset_value: UNDEFINED_LEGAL + LPF: + location: 13 + description: | + *Load Page Fault* + + Controls delegation of Load Page Fault exceptions to VS-mode. + + See `medeleg.LPF` for details. + type: RW + reset_value: UNDEFINED_LEGAL + SPF: + location: 15 + description: | + *Store/AMO Page Fault* + + Controls delegation of Store/AMO Page Fault exceptions to VS-mode. + + See `medeleg.SPF` for details. + type: RW + reset_value: UNDEFINED_LEGAL + IGPF: + location: 20 + description: | + *Instruction Guest Page Fault* + + Instruction Guest Page Fault exceptions _cannot be delegated to VS-mode_, + so this field is read-only 0. + + See `medeleg.IGPF` for details. + type: RO + reset_value: 0 + LGPF: + location: 21 + description: | + *Load Guest Page Fault* + + Load Guest Page Fault exceptions _cannot be delegated to VS-mode_, + so this field is read-only 0. + + See `medeleg.LGPF` for details. + type: RO + reset_value: 0 + VI: + location: 22 + description: | + *Virtual Instruction* + + Virtual Instruction exceptions _cannot be delegated to VS-mode_, + so this field is read-only 0. + + See `medeleg.VI` for details. + type: RO + reset_value: 0 + SGPF: + location: 23 + description: | + *Store/AMO Guest Page Fault* + + Store/AMO Guest Page Fault exceptions _cannot be delegated to VS-mode_, + so this field is read-only 0. + + See `medeleg.SGPF` for details. + type: RO + reset_value: 0 diff --git a/arch/csr/hedelegh.yaml b/arch/csr/hedelegh.yaml index 95ea3b951..fc1ad672e 100644 --- a/arch/csr/hedelegh.yaml +++ b/arch/csr/hedelegh.yaml @@ -1,14 +1,16 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -hedelegh: - long_name: Hypervisor Exception Delegation High - address: 0x612 - base: 32 - priv_mode: S - length: 32 - description: | - Controls exception delegation from HS-mode to VS-mode. +$schema: "csr_schema.json#" +kind: csr +name: hedelegh +long_name: Hypervisor Exception Delegation High +address: 0x612 +base: 32 +priv_mode: S +length: 32 +description: | + Controls exception delegation from HS-mode to VS-mode. - Alias of upper bits of `hedeleg`[63:32]. - definedBy: H - fields: {} + Alias of upper bits of `hedeleg`[63:32]. +definedBy: H +fields: {} diff --git a/arch/csr/hstatus.yaml b/arch/csr/hstatus.yaml index 501374789..eb2c5940d 100644 --- a/arch/csr/hstatus.yaml +++ b/arch/csr/hstatus.yaml @@ -1,244 +1,246 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -hstatus: - long_name: Hypervisor Status - address: 0x600 - priv_mode: S - length: SXLEN - description: | - The hstatus register tracks and controls a VS-mode guest. - - Unlike fields in `sstatus`, which are all aliases of fields `mstatus`, - bits in `hstatus` are independent bits and do not have aliases. - definedBy: H - fields: - VSXL: - location: 33-32 - base: 64 - description: | - *VS-mode XLen* - - [when,"VSXLEN == 3264"] - -- - Determines the effective XLEN in VS-mode. Valid values are: - - [separator="!"] - !=== - ! Value ! VSXLEN - - ! 0 ! 32 - ! 1 ! 64 - !=== - - -- - - [when,"VSXLEN = 32"] - Because the implementation only supports a single VSXLEN == 32, this field is read-only-0. - - [when,"VSXLEN = 64"] - Because the implementation only supports a single VSXLEN == 64, this field is read-only-1. - - - type(): | - if ((VSXLEN == 32) || (VSXLEN == 64)) { - return CsrFieldType::RO; - } else { - return CsrFieldType::RW; - } - reset_value(): | - if (VSXLEN == 32) { - # immutable, always 0 - return 0; - } else if (VSXLEN == 64) { - # immutable, always 1 - return 1; - } else { - # mutable, undefined reset state - return UNDEFINED_LEGAL; - } - sw_write(csr_value): | - if (CSR[mstatus].SXL < csr_value.VSXL) { - # cannot set VSXLEN less than SXLEN - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if ((csr_value.VSXL & 0b10) != 0) { - # MSB of VSXL represents XLEN > 64, which isn't legal - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.VSXL; - } - VTSR: - location: 22 - description: | - *Virtual Trap SRET* - - When `hstatus.VTSR` is set, executing the `sret` instruction in VS-mode - raises a `Virtual Instruction` exception. - - When `hstatus.VTSR` is clear, an `sret` instruction in VS-mode returns control - to the mode stored in `vsstatus.SPP`. - type: RW - reset_value: UNDEFINED_LEGAL - VTW: - location: 21 - description: | - *Virtual Trap WFI* - - When `hstatus.VTW` is set, a `wfi` instruction executed in VS-mode raises - a `Virtual Instruction` exception after waiting an implementation-defined - amount of time (which can be 0). - - When both `hstatus.VTW` and `mstatus.TW` are clear, a `wfi` instruction - executes in VS-mode without a timeout period. - - The `wfi` instruction is also affected by `mstatus.TW`, as shown below: - - [separator="!",%autowidth,%footer] - !=== - .2+! [.rotate]#`mstatus.TW`# .2+! [.rotate]#`hstatus.VTW`# 4+^.>! `wfi` behavior - h! HS-mode h! U-mode h! VS-mode h! VU-mode - - ! 0 ! 0 ! Wait ! Trap (I) ! Wait ! Trap (V) - ! 0 ! 1 ! Wait ! Trap (I) ! Trap (V) ! Trap (V) - ! 1 ! - ! Trap (I) ! Trap (I) ! Trap (I) ! Trap (I) - - 6+! Trap (I) - Trap with `Illegal Instruction` code + - Trap (V) - Trap with `Virtual Instruction` code - !=== - type: RW - reset_value: UNDEFINED_LEGAL - VTVM: - location: 20 - description: | - *Virtual Trap Virtual Memory* - - When set, a 'Virtual Instruction` trap occurs when executing an `sfence.vma`, `sinval.vma`, - or an explicit CSR access of the `satp` (really `vsatp`) register when in VS-mode. - - When clear, the instructions execute as normal in VS-mode. - - Notably, `hstatus.VTVM` does *not* cause `hfence.vvma`, `sfence.w.inval`, or `sfence.inval.ir` to trap. - - `mstatus.TVM` does not affect the VS-mode instructions controlled by `hstatus.TVTM`. - type: RW - reset_value: UNDEFINED_LEGAL - VGEIN: - location: 17-12 - description: | - *Virtual Guest External Interrupt Number* - - Selects the guest external interrupt source for VS-level external interrupts. - - When `hstatus.VGEIN` == 0, no external interrupt source is selected. - - When `hstatus.VGEIN` != 0, it selects which bit of `hgeip` is currently active in VS-mode. - - type(): | - # if NUM_EXTERNAL_GUEST_INTERRUPTS+1 is 63 (beacuse indexing in `hgeip` starts at 1), - # then the field accepts any value. - # Otherwise, it accepts a restricted set of values - if (NUM_EXTERNAL_GUEST_INTERRUPTS == 63) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RWR; - } - reset_value: UNDEFINED_LEGAL - legal?(csr_value): | - return csr_value.VGEIN <= NUM_EXTERNAL_GUEST_INTERRUPTS; - sw_write(csr_value): | - if (csr_value.VGEIN <= NUM_EXTERNAL_GUEST_INTERRUPTS) { - return csr_value.VGEIN; - } else { - return ILLEGAL_WLRL; - } - HU: - location: 9 - description: | - *Hypervisor in U-mode* - - When set, the hypervisor load/store instructions (`hlv`, `hlvx`, and `hsv`) can be - executed in U-mode. - - When clear, the hypervisor load/store instructions cause an `Illegal Instruction` trap. - type: RW - reset_value: UNDEFINED_LEGAL - SPVP: - location: 8 - description: | - *Supervisor Previous Virtual Privilege* - - Written by hardware: - - * When taking a trap into HS-mode from VS-mode or VU-mode, `hstatus.SPVP` is written with the nominal privlege mode - - Notably, unlike its analog `mstatus.SPP`, `hstatus.SPVP` is *not* cleared when returning from a trap. - - Can also be written by software without immediate side-effect. - - Affects execution by: - - * Controls the effective privilege level applied to the hypervisor load/store instructions, `hlv`, `hlvx`, and `hsv`. - type: RW - reset_value: UNDEFINED_LEGAL - SPV: - location: 7 - description: | - *Supervisor Previous Virtualization Mode* - - Written by hardware: - - * On a trap into HS-mode, hardware writes 1 when the prior mode was VS-mode or VU-mode, and 0 otherwise. - - Can also be written by software without immediate side-effect. - - Affects execution by: - - * When an `sret` instruction in executed in HS-mode or M-mode, - control returns to VS-mode or VU-mode (as selected by `mstatus.SPP`) when - `hstatus.SPV` is 1 and to HS-mode or U-mode otherwise. - type: RW - reset_value: UNDEFINED_LEGAL - GVA: - location: 6 - description: | - *Guest Virtual Address* - - Written by hardware whenever a trap is taken into HS-mode: - - * Writes 1 when a trap causes a guest virtual address to be written into `stval` (`Breakpoint`, `* Address Misaligned`, `* Access Fault`, `* Page Fault`, or `* Guest-Page Fault`). - * Writes 0 otherwise - - Does not affect execution. - type: RW - reset_value: UNDEFINED_LEGAL - VSBE: - location: 5 - description: | - *VS-mode Big Endian* - - Controls the endianness of data VS-mode (0 = little, 1 = big). - Instructions are always little endian, regardless of the data setting. - - [when,"VS_MODE_ENDIANESS == little"] - Since the CPU does not support big endian in VS-mode, this is hardwired to 0. - - [when,"VS_MODE_ENDIANESS == bit"] - Since the CPU does not support litte endian in VS-mode, this is hardwired to 1. - type(): | - if (VS_MODE_ENDIANESS == "dynamic") { - # mode is mutable - return CsrFieldType::RW; - } else { - # mode is fixed as either little or big endian - return CsrFieldType::RO; - } - reset_value(): | - if (VS_MODE_ENDIANESS == "little") { - # little endian - return 0; - } else if (VS_MODE_ENDIANESS == "big") { - # big endian - return 1; - } else { - # mutable - return UNDEFINED_LEGAL; - } +$schema: "csr_schema.json#" +kind: csr +name: hstatus +long_name: Hypervisor Status +address: 0x600 +priv_mode: S +length: SXLEN +description: | + The hstatus register tracks and controls a VS-mode guest. + + Unlike fields in `sstatus`, which are all aliases of fields `mstatus`, + bits in `hstatus` are independent bits and do not have aliases. +definedBy: H +fields: + VSXL: + location: 33-32 + base: 64 + description: | + *VS-mode XLen* + + [when,"VSXLEN == 3264"] + -- + Determines the effective XLEN in VS-mode. Valid values are: + + [separator="!"] + !=== + ! Value ! VSXLEN + + ! 0 ! 32 + ! 1 ! 64 + !=== + + -- + + [when,"VSXLEN = 32"] + Because the implementation only supports a single VSXLEN == 32, this field is read-only-0. + + [when,"VSXLEN = 64"] + Because the implementation only supports a single VSXLEN == 64, this field is read-only-1. + + + type(): | + if ((VSXLEN == 32) || (VSXLEN == 64)) { + return CsrFieldType::RO; + } else { + return CsrFieldType::RW; + } + reset_value(): | + if (VSXLEN == 32) { + # immutable, always 0 + return 0; + } else if (VSXLEN == 64) { + # immutable, always 1 + return 1; + } else { + # mutable, undefined reset state + return UNDEFINED_LEGAL; + } + sw_write(csr_value): | + if (CSR[mstatus].SXL < csr_value.VSXL) { + # cannot set VSXLEN less than SXLEN + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if ((csr_value.VSXL & 0b10) != 0) { + # MSB of VSXL represents XLEN > 64, which isn't legal + return UNDEFINED_LEGAL_DETERMINISTIC; + } else { + return csr_value.VSXL; + } + VTSR: + location: 22 + description: | + *Virtual Trap SRET* + + When `hstatus.VTSR` is set, executing the `sret` instruction in VS-mode + raises a `Virtual Instruction` exception. + + When `hstatus.VTSR` is clear, an `sret` instruction in VS-mode returns control + to the mode stored in `vsstatus.SPP`. + type: RW + reset_value: UNDEFINED_LEGAL + VTW: + location: 21 + description: | + *Virtual Trap WFI* + + When `hstatus.VTW` is set, a `wfi` instruction executed in VS-mode raises + a `Virtual Instruction` exception after waiting an implementation-defined + amount of time (which can be 0). + + When both `hstatus.VTW` and `mstatus.TW` are clear, a `wfi` instruction + executes in VS-mode without a timeout period. + + The `wfi` instruction is also affected by `mstatus.TW`, as shown below: + + [separator="!",%autowidth,%footer] + !=== + .2+! [.rotate]#`mstatus.TW`# .2+! [.rotate]#`hstatus.VTW`# 4+^.>! `wfi` behavior + h! HS-mode h! U-mode h! VS-mode h! VU-mode + + ! 0 ! 0 ! Wait ! Trap (I) ! Wait ! Trap (V) + ! 0 ! 1 ! Wait ! Trap (I) ! Trap (V) ! Trap (V) + ! 1 ! - ! Trap (I) ! Trap (I) ! Trap (I) ! Trap (I) + + 6+! Trap (I) - Trap with `Illegal Instruction` code + + Trap (V) - Trap with `Virtual Instruction` code + !=== + type: RW + reset_value: UNDEFINED_LEGAL + VTVM: + location: 20 + description: | + *Virtual Trap Virtual Memory* + + When set, a 'Virtual Instruction` trap occurs when executing an `sfence.vma`, `sinval.vma`, + or an explicit CSR access of the `satp` (really `vsatp`) register when in VS-mode. + + When clear, the instructions execute as normal in VS-mode. + + Notably, `hstatus.VTVM` does *not* cause `hfence.vvma`, `sfence.w.inval`, or `sfence.inval.ir` to trap. + + `mstatus.TVM` does not affect the VS-mode instructions controlled by `hstatus.TVTM`. + type: RW + reset_value: UNDEFINED_LEGAL + VGEIN: + location: 17-12 + description: | + *Virtual Guest External Interrupt Number* + + Selects the guest external interrupt source for VS-level external interrupts. + + When `hstatus.VGEIN` == 0, no external interrupt source is selected. + + When `hstatus.VGEIN` != 0, it selects which bit of `hgeip` is currently active in VS-mode. + + type(): | + # if NUM_EXTERNAL_GUEST_INTERRUPTS+1 is 63 (beacuse indexing in `hgeip` starts at 1), + # then the field accepts any value. + # Otherwise, it accepts a restricted set of values + if (NUM_EXTERNAL_GUEST_INTERRUPTS == 63) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RWR; + } + reset_value: UNDEFINED_LEGAL + legal?(csr_value): | + return csr_value.VGEIN <= NUM_EXTERNAL_GUEST_INTERRUPTS; + sw_write(csr_value): | + if (csr_value.VGEIN <= NUM_EXTERNAL_GUEST_INTERRUPTS) { + return csr_value.VGEIN; + } else { + return ILLEGAL_WLRL; + } + HU: + location: 9 + description: | + *Hypervisor in U-mode* + + When set, the hypervisor load/store instructions (`hlv`, `hlvx`, and `hsv`) can be + executed in U-mode. + + When clear, the hypervisor load/store instructions cause an `Illegal Instruction` trap. + type: RW + reset_value: UNDEFINED_LEGAL + SPVP: + location: 8 + description: | + *Supervisor Previous Virtual Privilege* + + Written by hardware: + + * When taking a trap into HS-mode from VS-mode or VU-mode, `hstatus.SPVP` is written with the nominal privlege mode + + Notably, unlike its analog `mstatus.SPP`, `hstatus.SPVP` is *not* cleared when returning from a trap. + + Can also be written by software without immediate side-effect. + + Affects execution by: + + * Controls the effective privilege level applied to the hypervisor load/store instructions, `hlv`, `hlvx`, and `hsv`. + type: RW + reset_value: UNDEFINED_LEGAL + SPV: + location: 7 + description: | + *Supervisor Previous Virtualization Mode* + + Written by hardware: + + * On a trap into HS-mode, hardware writes 1 when the prior mode was VS-mode or VU-mode, and 0 otherwise. + + Can also be written by software without immediate side-effect. + + Affects execution by: + + * When an `sret` instruction in executed in HS-mode or M-mode, + control returns to VS-mode or VU-mode (as selected by `mstatus.SPP`) when + `hstatus.SPV` is 1 and to HS-mode or U-mode otherwise. + type: RW + reset_value: UNDEFINED_LEGAL + GVA: + location: 6 + description: | + *Guest Virtual Address* + + Written by hardware whenever a trap is taken into HS-mode: + + * Writes 1 when a trap causes a guest virtual address to be written into `stval` (`Breakpoint`, `* Address Misaligned`, `* Access Fault`, `* Page Fault`, or `* Guest-Page Fault`). + * Writes 0 otherwise + + Does not affect execution. + type: RW + reset_value: UNDEFINED_LEGAL + VSBE: + location: 5 + description: | + *VS-mode Big Endian* + + Controls the endianness of data VS-mode (0 = little, 1 = big). + Instructions are always little endian, regardless of the data setting. + + [when,"VS_MODE_ENDIANESS == little"] + Since the CPU does not support big endian in VS-mode, this is hardwired to 0. + + [when,"VS_MODE_ENDIANESS == bit"] + Since the CPU does not support litte endian in VS-mode, this is hardwired to 1. + type(): | + if (VS_MODE_ENDIANESS == "dynamic") { + # mode is mutable + return CsrFieldType::RW; + } else { + # mode is fixed as either little or big endian + return CsrFieldType::RO; + } + reset_value(): | + if (VS_MODE_ENDIANESS == "little") { + # little endian + return 0; + } else if (VS_MODE_ENDIANESS == "big") { + # big endian + return 1; + } else { + # mutable + return UNDEFINED_LEGAL; + } diff --git a/arch/csr/instret.yaml b/arch/csr/instret.yaml index 00259a3cd..7f45d0160 100644 --- a/arch/csr/instret.yaml +++ b/arch/csr/instret.yaml @@ -1,69 +1,71 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -instret: - long_name: Instructions retired counter for RDINSTRET Instruction - address: 0xC02 - description: | - Alias for M-mode CSR `minstret`. +$schema: "csr_schema.json#" +kind: csr +name: instret +long_name: Instructions retired counter for RDINSTRET Instruction +address: 0xC02 +description: | + Alias for M-mode CSR `minstret`. - Privilege mode access is controlled with `mcounteren.IR`, `scounteren.IR`, and `hcounteren.IR` as follows: + Privilege mode access is controlled with `mcounteren.IR`, `scounteren.IR`, and `hcounteren.IR` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.IR`# .2+h! [.rotate]#`scounteren.IR`# .2+h! [.rotate]#`hcounteren.IR`# - 4+^.>h! `instret` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.IR`# .2+h! [.rotate]#`scounteren.IR`# .2+h! [.rotate]#`hcounteren.IR`# + 4+^.>h! `instret` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 64 - definedBy: Zicntr - fields: - COUNT: - location: 63-0 - alias: minstret.COUNT - description: Alias of `minstret.COUNT`. - type: RO-H - reset_value: 0 - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 64 +definedBy: Zicntr +fields: + COUNT: + location: 63-0 + alias: minstret.COUNT + description: Alias of `minstret.COUNT`. + type: RO-H + reset_value: 0 +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].IR == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].IR == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].IR & CSR[scounteren].IR) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].IR == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].IR == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].IR == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].IR & CSR[scounteren].IR) == 1'b0) && (CSR[mcounteren].IR == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].IR == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].IR & CSR[scounteren].IR) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].IR == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].IR == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].IR == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].IR & CSR[scounteren].IR) == 1'b0) && (CSR[mcounteren].IR == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].IR == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return CSR[minstret].COUNT; \ No newline at end of file + return CSR[minstret].COUNT; \ No newline at end of file diff --git a/arch/csr/instreth.yaml b/arch/csr/instreth.yaml index 4ffee66e2..f4a610ccb 100644 --- a/arch/csr/instreth.yaml +++ b/arch/csr/instreth.yaml @@ -1,72 +1,74 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -instreth: - long_name: Instructions retired counter, high bits - address: 0xC82 - base: 32 - description: | - Alias for high bits of M-mode CSR `minstret`[63:32]. +$schema: "csr_schema.json#" +kind: csr +name: instreth +long_name: Instructions retired counter, high bits +address: 0xC82 +base: 32 +description: | + Alias for high bits of M-mode CSR `minstret`[63:32]. - Privilege mode access is controlled with `mcounteren.IR`, `scounteren.IR`, and `hcounteren.IR` as follows: + Privilege mode access is controlled with `mcounteren.IR`, `scounteren.IR`, and `hcounteren.IR` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.IR`# .2+h! [.rotate]#`scounteren.IR`# .2+h! [.rotate]#`hcounteren.IR`# - 4+^.>h! `instret` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.IR`# .2+h! [.rotate]#`scounteren.IR`# .2+h! [.rotate]#`hcounteren.IR`# + 4+^.>h! `instret` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` - ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` - ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - priv_mode: U - length: 32 - definedBy: Zicntr - fields: - COUNT: - location: 31-0 - alias: minstret.COUNT[63:32] - description: Alias of `minstret.COUNT`[63:32]. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + ! 0 ! - ! - ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` ! `IllegalInstruction` + ! 1 ! 0 ! 0 ! read-only ! `IllegalInstruction` ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `VirtualInstruction` ! `VirtualInstruction` + ! 1 ! 0 ! 1 ! read-only ! `IllegalInstruction` ! read-only ! `VirtualInstruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== +priv_mode: U +length: 32 +definedBy: Zicntr +fields: + COUNT: + location: 31-0 + alias: minstret.COUNT[63:32] + description: Alias of `minstret.COUNT`[63:32]. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].IR == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].IR == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].IR & CSR[scounteren].IR) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].IR == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].IR == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].IR == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].IR & CSR[scounteren].IR) == 1'b0) && (CSR[mcounteren].IR == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].IR == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].IR & CSR[scounteren].IR) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].IR == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].IR == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].IR == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].IR & CSR[scounteren].IR) == 1'b0) && (CSR[mcounteren].IR == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].IR == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - # since the counter may be shared among harts, reads must be handled - # as a builtin function - return read_mcycle(); \ No newline at end of file + # since the counter may be shared among harts, reads must be handled + # as a builtin function + return read_mcycle(); \ No newline at end of file diff --git a/arch/csr/marchid.yaml b/arch/csr/marchid.yaml index 41d8260d8..fc7e8d8dd 100644 --- a/arch/csr/marchid.yaml +++ b/arch/csr/marchid.yaml @@ -1,50 +1,52 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -marchid: - long_name: Machine Architecture ID - address: 0xf12 - priv_mode: M - length: MXLEN - description: | - The `marchid` CSR is an MXLEN-bit read-only register encoding the base - microarchitecture of the hart. This register must be readable in any - implementation, but a value of 0 can be returned to indicate the field - is not implemented. The combination of `mvendorid` and `marchid` should - uniquely identify the type of hart microarchitecture that is - implemented. +$schema: "csr_schema.json#" +kind: csr +name: marchid +long_name: Machine Architecture ID +address: 0xf12 +priv_mode: M +length: MXLEN +description: | + The `marchid` CSR is an MXLEN-bit read-only register encoding the base + microarchitecture of the hart. This register must be readable in any + implementation, but a value of 0 can be returned to indicate the field + is not implemented. The combination of `mvendorid` and `marchid` should + uniquely identify the type of hart microarchitecture that is + implemented. - Open-source project architecture IDs are allocated globally by RISC-V - International, and have non-zero architecture IDs with a zero - most-significant-bit (MSB). Commercial architecture IDs are allocated by - each commercial vendor independently, but must have the MSB set and - cannot contain zero in the remaining MXLEN-1 bits. + Open-source project architecture IDs are allocated globally by RISC-V + International, and have non-zero architecture IDs with a zero + most-significant-bit (MSB). Commercial architecture IDs are allocated by + each commercial vendor independently, but must have the MSB set and + cannot contain zero in the remaining MXLEN-1 bits. - [NOTE] - ==== - The intent is for the architecture ID to represent the microarchitecture - associated with the repo around which development occurs rather than a - particular organization. Commercial fabrications of open-source designs - should (and might be required by the license to) retain the original - architecture ID. This will aid in reducing fragmentation and tool - support costs, as well as provide attribution. Open-source architecture - IDs are administered by RISC-V International and should only be - allocated to released, functioning open-source projects. Commercial - architecture IDs can be managed independently by any registered vendor - but are required to have IDs disjoint from the open-source architecture - IDs (MSB set) to prevent collisions if a vendor wishes to use both - closed-source and open-source microarchitectures. + [NOTE] + ==== + The intent is for the architecture ID to represent the microarchitecture + associated with the repo around which development occurs rather than a + particular organization. Commercial fabrications of open-source designs + should (and might be required by the license to) retain the original + architecture ID. This will aid in reducing fragmentation and tool + support costs, as well as provide attribution. Open-source architecture + IDs are administered by RISC-V International and should only be + allocated to released, functioning open-source projects. Commercial + architecture IDs can be managed independently by any registered vendor + but are required to have IDs disjoint from the open-source architecture + IDs (MSB set) to prevent collisions if a vendor wishes to use both + closed-source and open-source microarchitectures. - The convention adopted within the following Implementation field can be - used to segregate branches of the same architecture design, including by - organization. The `misa` register also helps distinguish different - variants of a design. - ==== + The convention adopted within the following Implementation field can be + used to segregate branches of the same architecture design, including by + organization. The `misa` register also helps distinguish different + variants of a design. + ==== - definedBy: Sm - fields: - Architecture: - location_rv32: 31-0 - location_rv64: 63-0 - type: RO - description: Vendor-specific microarchitecture ID. - reset_value(): return ARCH_ID; +definedBy: Sm +fields: + Architecture: + location_rv32: 31-0 + location_rv64: 63-0 + type: RO + description: Vendor-specific microarchitecture ID. + reset_value(): return ARCH_ID; diff --git a/arch/csr/mcause.yaml b/arch/csr/mcause.yaml index 3de9bf7a2..5f64818bf 100644 --- a/arch/csr/mcause.yaml +++ b/arch/csr/mcause.yaml @@ -1,87 +1,89 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mcause: - long_name: Machine Cause - address: 0x342 - priv_mode: M - length: MXLEN - description: Reports the cause of the latest exception. - definedBy: Sm - fields: - INT: - location_rv32: 31 - location_rv64: 63 - description: | - Written by hardware when a trap is taken into M-mode. - - When set, the last exception was caused by an asynchronous Interrupt. +$schema: "csr_schema.json#" +kind: csr +name: mcause +long_name: Machine Cause +address: 0x342 +priv_mode: M +length: MXLEN +description: Reports the cause of the latest exception. +definedBy: Sm +fields: + INT: + location_rv32: 31 + location_rv64: 63 + description: | + Written by hardware when a trap is taken into M-mode. + + When set, the last exception was caused by an asynchronous Interrupt. - `mcause.INT` is writeable. + `mcause.INT` is writeable. - [when,"TRAP_ON_ILLEGAL_WLRL == true"] - If `mcause` is written with an undefined cause (combination of `mcause.INT` and `mcause.CODE`), an `Illegal Instruction` exception occurs. + [when,"TRAP_ON_ILLEGAL_WLRL == true"] + If `mcause` is written with an undefined cause (combination of `mcause.INT` and `mcause.CODE`), an `Illegal Instruction` exception occurs. - [when,"TRAP_ON_ILLEGAL_WLRL == false"] - If `mcause` is written with an undefined cause (combination of `mcause.INT` and `mcause.CODE`), neither `mcause.INT` nor `mcause.CODE` are modified. - type: RW-RH - reset_value: 0 - sw_write(csr_value): | - # the write only holds if the INT/CODE combination is valid - if (csr_value.INT == 1) { - if (valid_interrupt_code?(csr_value.CODE)) { - return 1; - } - return ILLEGAL_WLRL; - } else { - if (valid_exception_code?(csr_value.CODE)) { - return 1; - } - return ILLEGAL_WLRL; + [when,"TRAP_ON_ILLEGAL_WLRL == false"] + If `mcause` is written with an undefined cause (combination of `mcause.INT` and `mcause.CODE`), neither `mcause.INT` nor `mcause.CODE` are modified. + type: RW-RH + reset_value: 0 + sw_write(csr_value): | + # the write only holds if the INT/CODE combination is valid + if (csr_value.INT == 1) { + if (valid_interrupt_code?(csr_value.CODE)) { + return 1; } - CODE: - location_rv32: 30-0 - location_rv64: 62-0 - description: | - Written by hardware when a trap is taken into M-mode. + return ILLEGAL_WLRL; + } else { + if (valid_exception_code?(csr_value.CODE)) { + return 1; + } + return ILLEGAL_WLRL; + } + CODE: + location_rv32: 30-0 + location_rv64: 62-0 + description: | + Written by hardware when a trap is taken into M-mode. - Holds the interrupt or exception code for the last taken trap. + Holds the interrupt or exception code for the last taken trap. - `mcause.CODE` is writeable. + `mcause.CODE` is writeable. - [when,"TRAP_ON_ILLEGAL_WLRL == true"] - If `mcause` is written with an undefined cause (combination of `mcause.INT` and `mcause.CODE`), an `Illegal Instruction` exception occurs. + [when,"TRAP_ON_ILLEGAL_WLRL == true"] + If `mcause` is written with an undefined cause (combination of `mcause.INT` and `mcause.CODE`), an `Illegal Instruction` exception occurs. - [when,"TRAP_ON_ILLEGAL_WLRL == false"] - If `mcause` is written with an undefined cause (combination of `mcause.INT` and `mcause.CODE`), neither `mcause.INT` nor `mcause.CODE` are modified. + [when,"TRAP_ON_ILLEGAL_WLRL == false"] + If `mcause` is written with an undefined cause (combination of `mcause.INT` and `mcause.CODE`), neither `mcause.INT` nor `mcause.CODE` are modified. - Valid interrupt codes are: - [separator="!"] - !=== - <%- interrupt_codes.sort_by{ |code| code.num }.each do |code| -%> - ! <%= code.num %> ! <%= code.name %> - <%- end -%> - !=== + Valid interrupt codes are: + [separator="!"] + !=== + <%- interrupt_codes.sort_by{ |code| code.num }.each do |code| -%> + ! <%= code.num %> ! <%= code.name %> + <%- end -%> + !=== - Valid exception codes are: - [separator="!"] - !=== - <%- exception_codes.sort_by{ |code| code.num }.each do |code| -%> - ! <%= code.num %> ! <%= code.name %> - <%- end -%> - !=== - type: RW-RH - reset_value: 0 - sw_write(csr_value): | - # the write only holds if the INT/CODE combination is valid - if (csr_value.INT == 1) { - if (valid_interrupt_code?(csr_value.CODE)) { - return csr_value.CODE; - } - return ILLEGAL_WLRL; - } else { - if (valid_exception_code?(csr_value.CODE)) { - return csr_value.CODE; - } - return ILLEGAL_WLRL; + Valid exception codes are: + [separator="!"] + !=== + <%- exception_codes.sort_by{ |code| code.num }.each do |code| -%> + ! <%= code.num %> ! <%= code.name %> + <%- end -%> + !=== + type: RW-RH + reset_value: 0 + sw_write(csr_value): | + # the write only holds if the INT/CODE combination is valid + if (csr_value.INT == 1) { + if (valid_interrupt_code?(csr_value.CODE)) { + return csr_value.CODE; + } + return ILLEGAL_WLRL; + } else { + if (valid_exception_code?(csr_value.CODE)) { + return csr_value.CODE; } + return ILLEGAL_WLRL; + } diff --git a/arch/csr/mconfigptr.yaml b/arch/csr/mconfigptr.yaml index 7daee958b..49fad5cc8 100644 --- a/arch/csr/mconfigptr.yaml +++ b/arch/csr/mconfigptr.yaml @@ -1,53 +1,55 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mconfigptr: - long_name: Machine Configuration Pointer - address: 0xF15 - description: | - Holds a physical address pointer to the unified discovery data structure in Memory. - - The `mconfigptr` holds the physical - address of a configuration data structure. Software can traverse this - data structure to discover information about the harts, the platform, - and their configuration. - - The pointer alignment in bits must be no smaller than MXLEN: - i.e., if MXLEN is - latexmath:[$8\times n$], then `mconfigptr`[latexmath:[$\log_2n$]-1:0] - must be zero. - - The `mconfigptr` register must be implemented, but it may be zero to indicate the - configuration data structure does not exist or that an alternative - mechanism must be used to locate it. - - [NOTE] - ==== - The format and schema of the configuration data structure have yet to be - standardized. - - *** - - While the `mconfigptr` register will simply be hardwired in some implementations, - other implementations may provide a means to configure the value - returned on CSR reads. For example, `mconfigptr` might present the value - of a memory-mapped register that is programmed by the platform or by - M-mode software towards the beginning of the boot process. - ==== - - - priv_mode: M - length: MXLEN - definedBy: - name: Sm - version: ">=1.12" - fields: - ADDRESS: - location_rv32: 31-0 - location_rv64: 63-0 - description: Pointer to physical address of the Unified Discovery configuration data structure. - type: RO - reset_value(): | - return CONFIG_PTR_ADDRESS; - legal?(csr_value): | - # pointer must be natrually aligned to XLEN - return ((XLEN-1) | csr_value.ADDRESS) == 0; +$schema: "csr_schema.json#" +kind: csr +name: mconfigptr +long_name: Machine Configuration Pointer +address: 0xF15 +description: | + Holds a physical address pointer to the unified discovery data structure in Memory. + + The `mconfigptr` holds the physical + address of a configuration data structure. Software can traverse this + data structure to discover information about the harts, the platform, + and their configuration. + + The pointer alignment in bits must be no smaller than MXLEN: + i.e., if MXLEN is + latexmath:[$8\times n$], then `mconfigptr`[latexmath:[$\log_2n$]-1:0] + must be zero. + + The `mconfigptr` register must be implemented, but it may be zero to indicate the + configuration data structure does not exist or that an alternative + mechanism must be used to locate it. + + [NOTE] + ==== + The format and schema of the configuration data structure have yet to be + standardized. + + *** + + While the `mconfigptr` register will simply be hardwired in some implementations, + other implementations may provide a means to configure the value + returned on CSR reads. For example, `mconfigptr` might present the value + of a memory-mapped register that is programmed by the platform or by + M-mode software towards the beginning of the boot process. + ==== + + +priv_mode: M +length: MXLEN +definedBy: + name: Sm + version: ">=1.12" +fields: + ADDRESS: + location_rv32: 31-0 + location_rv64: 63-0 + description: Pointer to physical address of the Unified Discovery configuration data structure. + type: RO + reset_value(): | + return CONFIG_PTR_ADDRESS; + legal?(csr_value): | + # pointer must be natrually aligned to XLEN + return ((XLEN-1) | csr_value.ADDRESS) == 0; diff --git a/arch/csr/mcycle.yaml b/arch/csr/mcycle.yaml index feb9484ec..8fb8102f8 100644 --- a/arch/csr/mcycle.yaml +++ b/arch/csr/mcycle.yaml @@ -1,59 +1,61 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mcycle: - long_name: Machine Cycle Counter - definedBy: Zicntr - address: 0xB00 - description: | - Counts the number of clock cycles executed by the processor core on which - the hart is running. - The counter has 64-bit precision on all RV32 and RV64 harts. +$schema: "csr_schema.json#" +kind: csr +name: mcycle +long_name: Machine Cycle Counter +definedBy: Zicntr +address: 0xB00 +description: | + Counts the number of clock cycles executed by the processor core on which + the hart is running. + The counter has 64-bit precision on all RV32 and RV64 harts. - The `mcycle` CSR may be shared between harts on the same core, in which case - writes to `mcycle` will be visible to those harts. The platform should provide - a mechanism to indicate which harts share an `mcycle` CSR. - priv_mode: M - length: 64 - fields: - COUNT: - alias: - - cycle.COUNT - location: 63-0 - type: RW-RH - sw_write(csr_value): | - # since writes to this register may not be hart-local, it must be handled - # as a special case - if (xlen() == 32) { - return sw_write_mcycle({read_mcycle()[63:31], csr_value.COUNT[31:0]}); - } else { - return sw_write_mcycle(csr_value.COUNT); - } - description: | - Cycle counter. + The `mcycle` CSR may be shared between harts on the same core, in which case + writes to `mcycle` will be visible to those harts. The platform should provide + a mechanism to indicate which harts share an `mcycle` CSR. +priv_mode: M +length: 64 +fields: + COUNT: + alias: + - cycle.COUNT + location: 63-0 + type: RW-RH + sw_write(csr_value): | + # since writes to this register may not be hart-local, it must be handled + # as a special case + if (xlen() == 32) { + return sw_write_mcycle({read_mcycle()[63:31], csr_value.COUNT[31:0]}); + } else { + return sw_write_mcycle(csr_value.COUNT); + } + description: | + Cycle counter. - <%- if ext?(:Zicntr) -%> - Aliased as `cycle.CYCLE`. - <%- end -%> + <%- if ext?(:Zicntr) -%> + Aliased as `cycle.CYCLE`. + <%- end -%> - Increments every cycle unless: + Increments every cycle unless: - * `mcountinhibit.CY` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.CY`<%- end -%> is set - <%- if ext?(:Smcntrpmf) -%> - * `mcyclecfg.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `mcyclecfg.SINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `mcyclecfg.UINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `mcyclecfg.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is VS - * `mcyclecfg.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> - reset_value: UNDEFINED_LEGAL - affectedBy: [Zicntr, Smcntrpmf, Smcdeleg, Ssccfg] - sw_read(): | - # since the counter may be shared among harts, reads must be handled - # as a builtin function - return read_mcycle(); + * `mcountinhibit.CY` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.CY`<%- end -%> is set + <%- if ext?(:Smcntrpmf) -%> + * `mcyclecfg.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `mcyclecfg.SINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `mcyclecfg.UINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `mcyclecfg.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is VS + * `mcyclecfg.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> + reset_value: UNDEFINED_LEGAL + affectedBy: [Zicntr, Smcntrpmf, Smcdeleg, Ssccfg] +sw_read(): | + # since the counter may be shared among harts, reads must be handled + # as a builtin function + return read_mcycle(); diff --git a/arch/csr/mcycleh.yaml b/arch/csr/mcycleh.yaml index 989918663..fb1798174 100644 --- a/arch/csr/mcycleh.yaml +++ b/arch/csr/mcycleh.yaml @@ -1,31 +1,33 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mcycleh: - long_name: High-half machine Cycle Counter - definedBy: Zicntr - address: 0xB80 - description: | - High-half alias of `mcycle`. - priv_mode: M - length: 32 - base: 32 - fields: - COUNT: - location: 31-0 - type: RW-RH - sw_write(csr_value): | - # since writes to this register may not be hart-local, it must be handled - # as a special case - if (xlen() == 32) { - return sw_write_mcycle({csr_value.COUNT[31:0], read_mcycle()[31:0]}); - } else { - return sw_write_mcycle(csr_value.COUNT); - } - description: | - Alias of upper half of `mcycle.COUNT`. - reset_value: UNDEFINED_LEGAL - affectedBy: [Zicntr, Smcntrpmf, Smcdeleg, Ssccfg] - sw_read(): | - # since the counter may be shared among harts, reads must be handled - # as a builtin function - return read_mcycle()[63:32]; +$schema: "csr_schema.json#" +kind: csr +name: mcycleh +long_name: High-half machine Cycle Counter +definedBy: Zicntr +address: 0xB80 +description: | + High-half alias of `mcycle`. +priv_mode: M +length: 32 +base: 32 +fields: + COUNT: + location: 31-0 + type: RW-RH + sw_write(csr_value): | + # since writes to this register may not be hart-local, it must be handled + # as a special case + if (xlen() == 32) { + return sw_write_mcycle({csr_value.COUNT[31:0], read_mcycle()[31:0]}); + } else { + return sw_write_mcycle(csr_value.COUNT); + } + description: | + Alias of upper half of `mcycle.COUNT`. + reset_value: UNDEFINED_LEGAL + affectedBy: [Zicntr, Smcntrpmf, Smcdeleg, Ssccfg] +sw_read(): | + # since the counter may be shared among harts, reads must be handled + # as a builtin function + return read_mcycle()[63:32]; diff --git a/arch/csr/medeleg.yaml b/arch/csr/medeleg.yaml index 1f5273104..16a7b6c5c 100644 --- a/arch/csr/medeleg.yaml +++ b/arch/csr/medeleg.yaml @@ -1,654 +1,656 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -medeleg: - long_name: Machine Exception Delegation - address: 0x302 - priv_mode: M - length: 64 - description: | - Controls exception delegation from M-mode to (H)S-mode - <%- if ext?(:H) -%> - or, in conjunction with `hedeleg`, to VS-mode - <%- end -%> - . - - An exception cause is delegated to (H)S-mode when all of the following hold: - - * The corresponding field in `medeleg` is set. - * The current privilege level is not M-mode. - <%- if ext?(:H) -%> - * The same field in `hedeleg` is clear. - <%- end -%> - - <%- if ext?(:H) -%> - An exception cause is delegated to VS-mode when all of the following hold: - - * The corresponding field in `medeleg` is set. - * The corresponding field in `hedeleg` is set. - * The current privilege level is not M-mode or HS-mode. - <%- end -%> - - Otherwise, an exception cause is handled by M-mode. - - See xref:prose:interrupts.adoc[interrupt documentation] for more details. - definedBy: S # medeleg does not exist whe S-mode is not implemented - fields: - IAM: - location: 0 - description: | - *Instruction Address Misaligned* - - Delegates Instruction Address Misaligned exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Instruction Address Misaligned exceptions may be futher delegated to VS-mode if `hedeleg.IAM` is also set. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - <%- if ext?(:H) -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.IAM`# .2+! [.rotate]#`hedeleg.IAM`# 4+^.>! Current Mode - .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` - - ! 0 ! 0 ! M ! M ! M ! M - ! 0 ! 1 ! M ! M ! M ! M - ! 1 ! 0 ! M ! HS ! HS ! HS - ! 1 ! 1 ! M ! HS ! VS ! VS - !=== - <%- else -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.IAM`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `S-mode` - - ! 0 ! M ! M - ! 1 ! M ! S - !=== - <%- end -%> - type: RW - reset_value: UNDEFINED_LEGAL - IAF: - location: 1 - description: | - *Instruction Access Fault* - - Delegates Instruction Access Fault exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Instruction Access Fault exceptions may be futher delegated to VS-mode if `hedeleg.IAM` is also set. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - <%- if ext?(:H) -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.IAF`# .2+! [.rotate]#`hedeleg.IAF`# 4+^.>! Current Mode - .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` - - ! 0 ! 0 ! M ! M ! M ! M - ! 0 ! 1 ! M ! M ! M ! M - ! 1 ! 0 ! M ! HS ! HS ! HS - ! 1 ! 1 ! M ! HS ! VS ! VS - !=== - <%- else -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.IAF`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `S-mode` - - ! 0 ! M ! M - ! 1 ! M ! S - !=== - <%- end -%> - - type: RW - reset_value: UNDEFINED_LEGAL - II: - location: 2 - description: | - *Illegal Instruction* - - Delegates Illegal Instruction exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Illegal Instruction exceptions may be futher delegated to VS-mode if `hedeleg.II` is also set. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - <%- if ext?(:H) -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.II`# .2+! [.rotate]#`hedeleg.II`# 4+^.>! Current Mode - .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` - - ! 0 ! 0 ! M ! M ! M ! M - ! 0 ! 1 ! M ! M ! M ! M - ! 1 ! 0 ! M ! HS ! HS ! HS - ! 1 ! 1 ! M ! HS ! VS ! VS - !=== - <%- else -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.II`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `S-mode` - - ! 0 ! M ! M - ! 1 ! M ! S - !=== - <%- end -%> - type: RW - reset_value: UNDEFINED_LEGAL - B: - location: 3 - description: | - *Breakpoint* - - Delegates Breakpoint exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Breakpoint exceptions may be futher delegated to VS-mode if `hedeleg.B` is also set. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - <%- if ext?(:H) -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.B`# .2+! [.rotate]#`hedeleg.B`# 4+^.>! Current Mode - .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` - - ! 0 ! 0 ! M ! M ! M ! M - ! 0 ! 1 ! M ! M ! M ! M - ! 1 ! 0 ! M ! HS ! HS ! HS - ! 1 ! 1 ! M ! HS ! VS ! VS - !=== - <%- else -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.B`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `S-mode` - - ! 0 ! M ! M - ! 1 ! M ! S - !=== - <%- end -%> - type: RW - reset_value: UNDEFINED_LEGAL - LAM: - location: 4 - description: | - *Load Address Misaligned* - - Delegates Load Address Misaligned exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Load Address Misaligned exceptions may be futher delegated to VS-mode if `hedeleg.LAM` is also set. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - [when,"MISALIGNED_LDST == true"] - Note that because this implementation supports misaligned loads, this exception will never occur. - However, the writeable bit should be presented anyway. - - The handling mode is determined as follows: - - <%- if ext?(:H) -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.LAM`# .2+! [.rotate]#`hedeleg.LAM`# 4+^.>! Current Mode - .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` - - ! 0 ! 0 ! M ! M ! M ! M - ! 0 ! 1 ! M ! M ! M ! M - ! 1 ! 0 ! M ! HS ! HS ! HS - ! 1 ! 1 ! M ! HS ! VS ! VS - !=== - <%- else -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.LAM`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `S-mode` - - ! 0 ! M ! M - ! 1 ! M ! S - !=== - <%- end -%> - - type: RW - reset_value: UNDEFINED_LEGAL - LAF: - location: 5 - description: | - *Load Access Fault* - - Delegates Load Access Fault exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Load Access Fault exceptions may be futher delegated to VS-mode if `hedeleg.LAF` is also set. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - <%- if ext?(:H) -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.LAF`# .2+! [.rotate]#`hedeleg.LAF`# 4+^.>! Current Mode - .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` - - ! 0 ! 0 ! M ! M ! M ! M - ! 0 ! 1 ! M ! M ! M ! M - ! 1 ! 0 ! M ! HS ! HS ! HS - ! 1 ! 1 ! M ! HS ! VS ! VS - !=== - <%- else -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.LAF`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `S-mode` - - ! 0 ! M ! M - ! 1 ! M ! S - !=== - <%- end -%> - - type: RW - reset_value: UNDEFINED_LEGAL - SAM: - location: 6 - description: | - *Store/AMO Address Misaligned* - - Delegates Store/AMO Address Misaligned exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Store/AMO Address Misaligned exceptions may be futher delegated to VS-mode if `hedeleg.SAM` is also set. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - [when,"MISALIGNED_LDST == true && MISALIGNED_AMO == true"] - Note that beause the implementation supports misaligned stores and misaligned AMOs (or no AMOs), this exception will never occur. - Even so, the writeable bit should be presented anyway. - - The handling mode is determined as follows: - - <%- if ext?(:H) -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.SAM`# .2+! [.rotate]#`hedeleg.SAM`# 4+^.>! Current Mode - .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` - - ! 0 ! 0 ! M ! M ! M ! M - ! 0 ! 1 ! M ! M ! M ! M - ! 1 ! 0 ! M ! HS ! HS ! HS - ! 1 ! 1 ! M ! HS ! VS ! VS - !=== - <%- else -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.SAM`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `S-mode` - - ! 0 ! M ! M - ! 1 ! M ! S - !=== - <%- end -%> - - type: RW - reset_value: UNDEFINED_LEGAL - SAF: - location: 7 - description: | - *Store/AMO Access Fault* - - Delegates Store/AMO Access Fault exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Store/AMO Access Fault exceptions may be futher delegated to VS-mode if `hedeleg.SAM` is also set. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - <%- if ext?(:H) -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.SAF`# .2+! [.rotate]#`hedeleg.SAF`# 4+^.>! Current Mode - .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` - - ! 0 ! 0 ! M ! M ! M ! M - ! 0 ! 1 ! M ! M ! M ! M - ! 1 ! 0 ! M ! HS ! HS ! HS - ! 1 ! 1 ! M ! HS ! VS ! VS - !=== - <%- else -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.SAF`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `S-mode` - - ! 0 ! M ! M - ! 1 ! M ! S - !=== - <%- end -%> - type: RW - reset_value: UNDEFINED_LEGAL - EU: - location: 8 - description: | - *Environment Call from U-Mode* - - Delegates Environment Call from U-mode exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Enviornment Call from U-mode exceptions may be futher delegated to VS-mode if `hedeleg.EU` is also set. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - <%- if ext?(:H) -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.EU`# .2+! [.rotate]#`hedeleg.EU`# 4+^.>! Current Mode - .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` - - ! 0 ! 0 ! M ! M ! M ! M - ! 0 ! 1 ! M ! M ! M ! M - ! 1 ! 0 ! M ! HS ! HS ! HS - ! 1 ! 1 ! M ! HS ! VS ! VS - !=== - <%- else -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.EU`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `S-mode` - - ! 0 ! M ! M - ! 1 ! M ! S - !=== - <%- end -%> - - type: RW - reset_value: UNDEFINED_LEGAL - ES: - location: 9 - description: | - *Environment Call from S-Mode* - - Delegates Environment Call from S-mode exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Enviornment Call from S-mode exceptions _cannot be delegated to VS-mode_. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.ES`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `(H)S-mode` - - ! 0 ! M ! M - ! 1 ! M ! (H)S - !=== - type: RW - reset_value: UNDEFINED_LEGAL - EVS: - location: 10 - description: | - *Environment Call from VS-Mode* - - Delegates Environment Call from VS-mode exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Enviornment Call from S-mode exceptions _cannot be delegated to VS-mode_. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.EVS`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `(H)S-mode` - - ! 0 ! M ! M - ! 1 ! M ! (H)S - !=== - type: RW - reset_value: UNDEFINED_LEGAL - definedBy: H - EM: - location: 11 - description: | - *Environment Call from M-Mode* - - An Environment Call from M-mode cannot be delegated, so this is a read-only field. - - All Enviornment Call from M-mode exceptions are taken by M-mode. - type: RO - reset_value: 0 - IPF: - location: 12 - description: | - *Instruction Page Fault* - - Delegates Instruction Page Fault exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Instruction Page Fault exceptions may be futher delegated to VS-mode if `hedeleg.IPF` is also set. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - <%- if ext?(:H) -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.IPF`# .2+! [.rotate]#`hedeleg.IPF`# 4+^.>! Current Mode - .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` - - ! 0 ! 0 ! M ! M ! M ! M - ! 0 ! 1 ! M ! M ! M ! M - ! 1 ! 0 ! M ! HS ! HS ! HS - ! 1 ! 1 ! M ! HS ! VS ! VS - !=== - <%- else -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.IPF`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `S-mode` - - ! 0 ! M ! M - ! 1 ! M ! S - !=== - <%- end -%> - type: RW - reset_value: UNDEFINED_LEGAL - LPF: - location: 13 - description: | - *Load Page Fault* - - Delegates Load Page Fault exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Load Page Fault exceptions may be futher delegated to VS-mode if `hedeleg.LPF` is also set. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - <%- if ext?(:H) -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.LPF`# .2+! [.rotate]#`hedeleg.LPF`# 4+^.>! Current Mode - .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` - - ! 0 ! 0 ! M ! M ! M ! M - ! 0 ! 1 ! M ! M ! M ! M - ! 1 ! 0 ! M ! HS ! HS ! HS - ! 1 ! 1 ! M ! HS ! VS ! VS - !=== - <%- else -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.LPF`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `S-mode` - - ! 0 ! M ! M - ! 1 ! M ! S - !=== - <%- end -%> - - type: RW - reset_value: UNDEFINED_LEGAL - SPF: - location: 15 - description: | - *Store/AMO Page Fault* - - Delegates Store/AMO Page Fault exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Store/AMO Page Fault exceptions may be futher delegated to VS-mode if `hedeleg.SPF` is also set. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - <%- if ext?(:H) -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.SPF`# .2+! [.rotate]#`hedeleg.SPF`# 4+^.>! Current Mode - .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` - - ! 0 ! 0 ! M ! M ! M ! M - ! 0 ! 1 ! M ! M ! M ! M - ! 1 ! 0 ! M ! HS ! HS ! HS - ! 1 ! 1 ! M ! HS ! VS ! VS - !=== - <%- else -%> - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.LPF`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `S-mode` - - ! 0 ! M ! M - ! 1 ! M ! S - !=== - <%- end -%> - type: RW - reset_value: UNDEFINED_LEGAL - IGPF: - location: 20 - description: | - *Instruction Guest Page Fault* - - Delegates Instruction Guest Page Fault exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Instruction Guest Page Fault exceptions _cannot be delegated to VS-mode_. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.IGPF`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `(H)S-mode` - - ! 0 ! M ! M - ! 1 ! M ! HS - !=== - type: RW - reset_value: UNDEFINED_LEGAL - definedBy: H - LGPF: - location: 21 - description: | - *Load Guest Page Fault* - - Delegates Load Guest Page Fault exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Load Guest Page Fault exceptions _cannot be delegated to VS-mode_. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.LGPF`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `(H)S-mode` - - ! 0 ! M ! M - ! 1 ! M ! HS - !=== - - type: RW - reset_value: UNDEFINED_LEGAL - definedBy: H - VI: - location: 22 - description: | - *Virtual Instruction* - - Delegates Virtual Instruction exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Virtual Instruction exceptions _cannot be delegated to VS-mode_. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.VI`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `(H)S-mode` - - ! 0 ! M ! M - ! 1 ! M ! HS - !=== - - type: RW - reset_value: UNDEFINED_LEGAL - definedBy: H - SGPF: - location: 23 - description: | - *Store/AMO Guest Page Fault* - - Delegates Store/AMO Guest Page Fault exceptions to (H)S-mode. - <%- if ext?(:H) -%> - Store/AMO Guest Page Fault exceptions _cannot be delegated to VS-mode_. - <%- end -%> - - Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. - - The handling mode is determined as follows: - - [separator="!",%autowidth, %footer] - !=== - .2+! [.rotate]#`medeleg.SGPF`# 2+^.>! Current Mode - .>h! `M-mode` .>h! `(H)S-mode` - - ! 0 ! M ! M - ! 1 ! M ! HS - !=== - type: RW - reset_value: UNDEFINED_LEGAL - definedBy: H +$schema: "csr_schema.json#" +kind: csr +name: medeleg +long_name: Machine Exception Delegation +address: 0x302 +priv_mode: M +length: 64 +description: | + Controls exception delegation from M-mode to (H)S-mode + <%- if ext?(:H) -%> + or, in conjunction with `hedeleg`, to VS-mode + <%- end -%> + . + + An exception cause is delegated to (H)S-mode when all of the following hold: + + * The corresponding field in `medeleg` is set. + * The current privilege level is not M-mode. + <%- if ext?(:H) -%> + * The same field in `hedeleg` is clear. + <%- end -%> + + <%- if ext?(:H) -%> + An exception cause is delegated to VS-mode when all of the following hold: + + * The corresponding field in `medeleg` is set. + * The corresponding field in `hedeleg` is set. + * The current privilege level is not M-mode or HS-mode. + <%- end -%> + + Otherwise, an exception cause is handled by M-mode. + + See xref:prose:interrupts.adoc[interrupt documentation] for more details. +definedBy: S # medeleg does not exist whe S-mode is not implemented +fields: + IAM: + location: 0 + description: | + *Instruction Address Misaligned* + + Delegates Instruction Address Misaligned exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Instruction Address Misaligned exceptions may be futher delegated to VS-mode if `hedeleg.IAM` is also set. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + <%- if ext?(:H) -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.IAM`# .2+! [.rotate]#`hedeleg.IAM`# 4+^.>! Current Mode + .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` + + ! 0 ! 0 ! M ! M ! M ! M + ! 0 ! 1 ! M ! M ! M ! M + ! 1 ! 0 ! M ! HS ! HS ! HS + ! 1 ! 1 ! M ! HS ! VS ! VS + !=== + <%- else -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.IAM`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `S-mode` + + ! 0 ! M ! M + ! 1 ! M ! S + !=== + <%- end -%> + type: RW + reset_value: UNDEFINED_LEGAL + IAF: + location: 1 + description: | + *Instruction Access Fault* + + Delegates Instruction Access Fault exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Instruction Access Fault exceptions may be futher delegated to VS-mode if `hedeleg.IAM` is also set. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + <%- if ext?(:H) -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.IAF`# .2+! [.rotate]#`hedeleg.IAF`# 4+^.>! Current Mode + .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` + + ! 0 ! 0 ! M ! M ! M ! M + ! 0 ! 1 ! M ! M ! M ! M + ! 1 ! 0 ! M ! HS ! HS ! HS + ! 1 ! 1 ! M ! HS ! VS ! VS + !=== + <%- else -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.IAF`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `S-mode` + + ! 0 ! M ! M + ! 1 ! M ! S + !=== + <%- end -%> + + type: RW + reset_value: UNDEFINED_LEGAL + II: + location: 2 + description: | + *Illegal Instruction* + + Delegates Illegal Instruction exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Illegal Instruction exceptions may be futher delegated to VS-mode if `hedeleg.II` is also set. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + <%- if ext?(:H) -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.II`# .2+! [.rotate]#`hedeleg.II`# 4+^.>! Current Mode + .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` + + ! 0 ! 0 ! M ! M ! M ! M + ! 0 ! 1 ! M ! M ! M ! M + ! 1 ! 0 ! M ! HS ! HS ! HS + ! 1 ! 1 ! M ! HS ! VS ! VS + !=== + <%- else -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.II`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `S-mode` + + ! 0 ! M ! M + ! 1 ! M ! S + !=== + <%- end -%> + type: RW + reset_value: UNDEFINED_LEGAL + B: + location: 3 + description: | + *Breakpoint* + + Delegates Breakpoint exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Breakpoint exceptions may be futher delegated to VS-mode if `hedeleg.B` is also set. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + <%- if ext?(:H) -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.B`# .2+! [.rotate]#`hedeleg.B`# 4+^.>! Current Mode + .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` + + ! 0 ! 0 ! M ! M ! M ! M + ! 0 ! 1 ! M ! M ! M ! M + ! 1 ! 0 ! M ! HS ! HS ! HS + ! 1 ! 1 ! M ! HS ! VS ! VS + !=== + <%- else -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.B`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `S-mode` + + ! 0 ! M ! M + ! 1 ! M ! S + !=== + <%- end -%> + type: RW + reset_value: UNDEFINED_LEGAL + LAM: + location: 4 + description: | + *Load Address Misaligned* + + Delegates Load Address Misaligned exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Load Address Misaligned exceptions may be futher delegated to VS-mode if `hedeleg.LAM` is also set. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + [when,"MISALIGNED_LDST == true"] + Note that because this implementation supports misaligned loads, this exception will never occur. + However, the writeable bit should be presented anyway. + + The handling mode is determined as follows: + + <%- if ext?(:H) -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.LAM`# .2+! [.rotate]#`hedeleg.LAM`# 4+^.>! Current Mode + .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` + + ! 0 ! 0 ! M ! M ! M ! M + ! 0 ! 1 ! M ! M ! M ! M + ! 1 ! 0 ! M ! HS ! HS ! HS + ! 1 ! 1 ! M ! HS ! VS ! VS + !=== + <%- else -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.LAM`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `S-mode` + + ! 0 ! M ! M + ! 1 ! M ! S + !=== + <%- end -%> + + type: RW + reset_value: UNDEFINED_LEGAL + LAF: + location: 5 + description: | + *Load Access Fault* + + Delegates Load Access Fault exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Load Access Fault exceptions may be futher delegated to VS-mode if `hedeleg.LAF` is also set. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + <%- if ext?(:H) -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.LAF`# .2+! [.rotate]#`hedeleg.LAF`# 4+^.>! Current Mode + .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` + + ! 0 ! 0 ! M ! M ! M ! M + ! 0 ! 1 ! M ! M ! M ! M + ! 1 ! 0 ! M ! HS ! HS ! HS + ! 1 ! 1 ! M ! HS ! VS ! VS + !=== + <%- else -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.LAF`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `S-mode` + + ! 0 ! M ! M + ! 1 ! M ! S + !=== + <%- end -%> + + type: RW + reset_value: UNDEFINED_LEGAL + SAM: + location: 6 + description: | + *Store/AMO Address Misaligned* + + Delegates Store/AMO Address Misaligned exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Store/AMO Address Misaligned exceptions may be futher delegated to VS-mode if `hedeleg.SAM` is also set. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + [when,"MISALIGNED_LDST == true && MISALIGNED_AMO == true"] + Note that beause the implementation supports misaligned stores and misaligned AMOs (or no AMOs), this exception will never occur. + Even so, the writeable bit should be presented anyway. + + The handling mode is determined as follows: + + <%- if ext?(:H) -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.SAM`# .2+! [.rotate]#`hedeleg.SAM`# 4+^.>! Current Mode + .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` + + ! 0 ! 0 ! M ! M ! M ! M + ! 0 ! 1 ! M ! M ! M ! M + ! 1 ! 0 ! M ! HS ! HS ! HS + ! 1 ! 1 ! M ! HS ! VS ! VS + !=== + <%- else -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.SAM`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `S-mode` + + ! 0 ! M ! M + ! 1 ! M ! S + !=== + <%- end -%> + + type: RW + reset_value: UNDEFINED_LEGAL + SAF: + location: 7 + description: | + *Store/AMO Access Fault* + + Delegates Store/AMO Access Fault exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Store/AMO Access Fault exceptions may be futher delegated to VS-mode if `hedeleg.SAM` is also set. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + <%- if ext?(:H) -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.SAF`# .2+! [.rotate]#`hedeleg.SAF`# 4+^.>! Current Mode + .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` + + ! 0 ! 0 ! M ! M ! M ! M + ! 0 ! 1 ! M ! M ! M ! M + ! 1 ! 0 ! M ! HS ! HS ! HS + ! 1 ! 1 ! M ! HS ! VS ! VS + !=== + <%- else -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.SAF`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `S-mode` + + ! 0 ! M ! M + ! 1 ! M ! S + !=== + <%- end -%> + type: RW + reset_value: UNDEFINED_LEGAL + EU: + location: 8 + description: | + *Environment Call from U-Mode* + + Delegates Environment Call from U-mode exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Enviornment Call from U-mode exceptions may be futher delegated to VS-mode if `hedeleg.EU` is also set. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + <%- if ext?(:H) -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.EU`# .2+! [.rotate]#`hedeleg.EU`# 4+^.>! Current Mode + .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` + + ! 0 ! 0 ! M ! M ! M ! M + ! 0 ! 1 ! M ! M ! M ! M + ! 1 ! 0 ! M ! HS ! HS ! HS + ! 1 ! 1 ! M ! HS ! VS ! VS + !=== + <%- else -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.EU`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `S-mode` + + ! 0 ! M ! M + ! 1 ! M ! S + !=== + <%- end -%> + + type: RW + reset_value: UNDEFINED_LEGAL + ES: + location: 9 + description: | + *Environment Call from S-Mode* + + Delegates Environment Call from S-mode exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Enviornment Call from S-mode exceptions _cannot be delegated to VS-mode_. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.ES`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `(H)S-mode` + + ! 0 ! M ! M + ! 1 ! M ! (H)S + !=== + type: RW + reset_value: UNDEFINED_LEGAL + EVS: + location: 10 + description: | + *Environment Call from VS-Mode* + + Delegates Environment Call from VS-mode exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Enviornment Call from S-mode exceptions _cannot be delegated to VS-mode_. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.EVS`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `(H)S-mode` + + ! 0 ! M ! M + ! 1 ! M ! (H)S + !=== + type: RW + reset_value: UNDEFINED_LEGAL + definedBy: H + EM: + location: 11 + description: | + *Environment Call from M-Mode* + + An Environment Call from M-mode cannot be delegated, so this is a read-only field. + + All Enviornment Call from M-mode exceptions are taken by M-mode. + type: RO + reset_value: 0 + IPF: + location: 12 + description: | + *Instruction Page Fault* + + Delegates Instruction Page Fault exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Instruction Page Fault exceptions may be futher delegated to VS-mode if `hedeleg.IPF` is also set. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + <%- if ext?(:H) -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.IPF`# .2+! [.rotate]#`hedeleg.IPF`# 4+^.>! Current Mode + .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` + + ! 0 ! 0 ! M ! M ! M ! M + ! 0 ! 1 ! M ! M ! M ! M + ! 1 ! 0 ! M ! HS ! HS ! HS + ! 1 ! 1 ! M ! HS ! VS ! VS + !=== + <%- else -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.IPF`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `S-mode` + + ! 0 ! M ! M + ! 1 ! M ! S + !=== + <%- end -%> + type: RW + reset_value: UNDEFINED_LEGAL + LPF: + location: 13 + description: | + *Load Page Fault* + + Delegates Load Page Fault exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Load Page Fault exceptions may be futher delegated to VS-mode if `hedeleg.LPF` is also set. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + <%- if ext?(:H) -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.LPF`# .2+! [.rotate]#`hedeleg.LPF`# 4+^.>! Current Mode + .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` + + ! 0 ! 0 ! M ! M ! M ! M + ! 0 ! 1 ! M ! M ! M ! M + ! 1 ! 0 ! M ! HS ! HS ! HS + ! 1 ! 1 ! M ! HS ! VS ! VS + !=== + <%- else -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.LPF`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `S-mode` + + ! 0 ! M ! M + ! 1 ! M ! S + !=== + <%- end -%> + + type: RW + reset_value: UNDEFINED_LEGAL + SPF: + location: 15 + description: | + *Store/AMO Page Fault* + + Delegates Store/AMO Page Fault exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Store/AMO Page Fault exceptions may be futher delegated to VS-mode if `hedeleg.SPF` is also set. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + <%- if ext?(:H) -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.SPF`# .2+! [.rotate]#`hedeleg.SPF`# 4+^.>! Current Mode + .>h! `M-mode` .>h! `HS-mode` .>h! `VS-mode` .>h! `VU-mode` + + ! 0 ! 0 ! M ! M ! M ! M + ! 0 ! 1 ! M ! M ! M ! M + ! 1 ! 0 ! M ! HS ! HS ! HS + ! 1 ! 1 ! M ! HS ! VS ! VS + !=== + <%- else -%> + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.LPF`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `S-mode` + + ! 0 ! M ! M + ! 1 ! M ! S + !=== + <%- end -%> + type: RW + reset_value: UNDEFINED_LEGAL + IGPF: + location: 20 + description: | + *Instruction Guest Page Fault* + + Delegates Instruction Guest Page Fault exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Instruction Guest Page Fault exceptions _cannot be delegated to VS-mode_. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.IGPF`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `(H)S-mode` + + ! 0 ! M ! M + ! 1 ! M ! HS + !=== + type: RW + reset_value: UNDEFINED_LEGAL + definedBy: H + LGPF: + location: 21 + description: | + *Load Guest Page Fault* + + Delegates Load Guest Page Fault exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Load Guest Page Fault exceptions _cannot be delegated to VS-mode_. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.LGPF`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `(H)S-mode` + + ! 0 ! M ! M + ! 1 ! M ! HS + !=== + + type: RW + reset_value: UNDEFINED_LEGAL + definedBy: H + VI: + location: 22 + description: | + *Virtual Instruction* + + Delegates Virtual Instruction exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Virtual Instruction exceptions _cannot be delegated to VS-mode_. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.VI`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `(H)S-mode` + + ! 0 ! M ! M + ! 1 ! M ! HS + !=== + + type: RW + reset_value: UNDEFINED_LEGAL + definedBy: H + SGPF: + location: 23 + description: | + *Store/AMO Guest Page Fault* + + Delegates Store/AMO Guest Page Fault exceptions to (H)S-mode. + <%- if ext?(:H) -%> + Store/AMO Guest Page Fault exceptions _cannot be delegated to VS-mode_. + <%- end -%> + + Exceptions are never taken into a less-privileged mode, regardless of `medeleg`. + + The handling mode is determined as follows: + + [separator="!",%autowidth, %footer] + !=== + .2+! [.rotate]#`medeleg.SGPF`# 2+^.>! Current Mode + .>h! `M-mode` .>h! `(H)S-mode` + + ! 0 ! M ! M + ! 1 ! M ! HS + !=== + type: RW + reset_value: UNDEFINED_LEGAL + definedBy: H diff --git a/arch/csr/medelegh.yaml b/arch/csr/medelegh.yaml index 4a75e09e4..bff63b2b0 100644 --- a/arch/csr/medelegh.yaml +++ b/arch/csr/medelegh.yaml @@ -1,14 +1,16 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -medelegh: - long_name: Machine Exception Delegation, High bits - address: 0x312 - priv_mode: M - length: 32 - base: 32 - description: | - Alias of the upper 32 bits of `medeleg`. - definedBy: - name: S - version: ">= 1.13" - fields: {} +$schema: "csr_schema.json#" +kind: csr +name: medelegh +long_name: Machine Exception Delegation, High bits +address: 0x312 +priv_mode: M +length: 32 +base: 32 +description: | + Alias of the upper 32 bits of `medeleg`. +definedBy: + name: S + version: ">= 1.13" +fields: {} diff --git a/arch/csr/menvcfg.yaml b/arch/csr/menvcfg.yaml index 32ecf268e..31b2d7e99 100644 --- a/arch/csr/menvcfg.yaml +++ b/arch/csr/menvcfg.yaml @@ -1,285 +1,287 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -menvcfg: - address: 0x30A - long_name: Machine Environment Configuration - description: | - Contains bits to enable/disable extensions - - The `menvcfg` CSR controls - certain characteristics of the execution environment for modes less - privileged than M. - - If bit FIOM (Fence of I/O implies Memory) is set to one in `menvcfg`, - FENCE instructions executed in modes less privileged than M are modified - so the requirement to order accesses to device I/O implies also the - requirement to order main memory accesses. <> - details the modified interpretation of FENCE instruction bits PI, PO, - SI, and SO for modes less privileged than M when FIOM=1. - - Similarly, for modes less privileged than M when FIOM=1, if an atomic - instruction that accesses a region ordered as device I/O has its _aq_ - and/or _rl_ bit set, then that instruction is ordered as though it - accesses both device I/O and memory. - - If S-mode is not supported, or if `satp`.MODE is read-only zero (always - Bare), the implementation may make FIOM read-only zero. - - [[menvcfg-FIOM]] - .Modified interpretation of FENCE predecessor and successor sets for modes less privileged than M when FIOM=1. - [separator="!",%autowidth,float="center",align="center",cols="^,<",options="header"] - !=== - !Instruction bit |Meaning when set - !PI + - PO - !Predecessor device input and memory reads (PR implied) + - Predecessor device output and memory writes (PW implied) - !SI + - SO - !Successor device input and memory reads (SR implied) + - Successor device output and memory writes (SW implied) - !=== - - [NOTE] - ==== - Bit FIOM is needed in `menvcfg` so M-mode can emulate the `H` (hypervisor) - extension, which has an - equivalent FIOM bit in the hypervisor CSR `henvcfg`. - ==== - - The PBMTE bit controls whether the Svpbmt extension is available for use - in S-mode and G-stage address translation (i.e., for page tables pointed - to by `satp` or `hgatp`). When PBMTE=1, Svpbmt is available for S-mode - and G-stage address translation. When PBMTE=0, the implementation - behaves as though Svpbmt were not implemented. If Svpbmt is not - implemented, PBMTE is read-only zero. Furthermore, for implementations - with the hypervisor extension, `henvcfg`.PBMTE is read-only zero if - `menvcfg`.PBMTE is zero. - - After changing `menvcfg`.PBMTE, executing an SFENCE.VMA instruction with - _rs1_=`x0` and _rs2_=`x0` suffices to synchronize address-translation caches - with respect to the altered interpretation of page-table entries' PBMT fields. - See <> for additional synchronization requirements when the - hypervisor extension is implemented. - - If the Svadu extension is implemented, the ADUE bit controls whether hardware - updating of PTE A/D bits is enabled for S-mode and G-stage address - translations. - When ADUE=1, hardware updating of PTE A/D bits is enabled during S-mode - address translation, and the implementation behaves as though the Svade - extension were not implemented for S-mode address translation. - When the hypervisor extension is implemented, if ADUE=1, hardware updating of - PTE A/D bits is enabled during G-stage address translation, and the - implementation behaves as though the Svade extension were not implemented for - G-stage address translation. - When ADUE=0, the implementation behaves as though Svade were implemented for - S-mode and G-stage address translation. - If Svadu is not implemented, ADUE is read-only zero. - Furthermore, for implementations with the hypervisor extension, `henvcfg`.ADUE - is read-only zero if `menvcfg`.ADUE is zero. - - NOTE: The Svade extension requires page-fault exceptions be raised when PTE - A/D bits need be set, hence Svade is implemented when ADUE=0. - - If the Smcdeleg extension is implemented, the CDE (Counter Delegation Enable) bit controls whether Zicntr and Zihpm counters can be delegated to S-mode. When CDE=1, the Smcdeleg extension is enabled, see <>. When CDE=0, the Smcdeleg and Ssccfg extensions appear to be not implemented. If Smcdeleg is not implemented, CDE is read-only zero. - - The definition of the STCE field is furnished by the Sstc extension. - - The definition of the CBZE field is furnished by the Zicboz extension. - - The definitions of the CBCFE and CBIE fields are furnished by the Zicbom extension. - - The definition of the PMM field will be furnished by the forthcoming - Smnpm extension. Its allocation within `menvcfg` may change prior to the - ratification of that extension. - - The Zicfilp extension adds the `LPE` field in `menvcfg`. When the `LPE` field is - set to 1 and S-mode is implemented, the Zicfilp extension is enabled in S-mode. - If `LPE` field is set to 1 and S-mode is not implemented, the Zicfilp extension - is enabled in U-mode. When the `LPE` field is 0, the Zicfilp extension is not - enabled in S-mode, and the following rules apply to S-mode. If the `LPE` field - is 0 and S-mode is not implemented, then the same rules apply to U-mode. - - * The hart does not update the `ELP` state; it remains as `NO_LP_EXPECTED`. - * The `LPAD` instruction operates as a no-op. - - The Zicfiss extension adds the `SSE` field to `menvcfg`. When the `SSE` field is - set to 1 the Zicfiss extension is activated in S-mode. When `SSE` field is 0, - the following rules apply to privilege modes that are less than M: - - * 32-bit Zicfiss instructions will revert to their behavior as defined by Zimop. - * 16-bit Zicfiss instructions will revert to their behavior as defined by Zcmop. - * The `pte.xwr=010b` encoding in VS/S-stage page tables becomes reserved. - * The `henvcfg.SSE` and `senvcfg.SSE` fields will read as zero and are read-only. - * `SSAMOSWAP.W/D` raises an illegal-instruction exception. - - The Ssdbltrp extension adds the double-trap-enable (`DTE`) field in `menvcfg`. - When `menvcfg.DTE` is zero, the implementation behaves as though Ssdbltrp is not - implemented. When Ssdbltrp is not implemented `sstatus.SDT`, `vsstatus.SDT`, and - `henvcfg.DTE` bits are read-only zero. - - When XLEN=32, `menvcfgh` is a 32-bit read/write register - that aliases bits 63:32 of `menvcfg`. - The `menvcfgh` register does not exist when XLEN=64. - - If U-mode is not supported, then registers `menvcfg` and `menvcfgh` do - not exist. - priv_mode: M - length: 64 - definedBy: - allOf: - - name: Sm - version: ">=1.12" - - name: U - fields: - STCE: - location: 63 - description: | - *STimecmp Enable* - - When set, `stimecmp` is operational. - - When clear, `stimecmp` access in a mode other than M-mode raises an `Illegal Instruction` trap. - S-mode timer interrupts will not be generated when clear, and `mip` and `sip` revert to their prior behavior without `Sstc`. - definedBy: Sstc - type: RW - reset_value: UNDEFINED_LEGAL - PBMTE: - location: 62 - description: | - *Page Based Memory Type Enable* - - The PBMTE bit controls whether the Svpbmt extension is available for use in S-mode<% if ext?(:H) %>and G-stage<% end %> - address translation (i.e., for page tables pointed to by satp<% if ext?(:H) %> or hgatp<% end %>). When PBMTE=1, Svpbmt is - available for S-mode <% if ext?(:H) %> and G-stage <% end %> address translation. When PBMTE=0, the implementation behaves - as though Svpbmt were not implemented. If Svpbmt is not implemented, PBMTE is read-only zero. - - <% if ext?(:H) %> - Furthermore, henvcfg.PBMTE is read-only zero if - menvcfg.PBMTE is zero. - <% end %> - - After changing `menvcfg.PBMTE`, executing an `sfence.vma` instruction with _rs1_=_x0_ and - _rs2_=_x0_ suffices to synchronize address-translation caches with respect to the altered - interpretation of page-table entries' PBMT fields. - - definedBy: Svpbmt - type: RW - reset_value: UNDEFINED_LEGAL - ADUE: - location: 61 - description: | - If the Svadu extension is implemented, the ADUE bit controls whether hardware updating of - PTE A/D bits is enabled for S-mode and G-stage address translations. When ADUE=1, hardware - updating of PTE A/D bits is enabled during S-mode address translation, and the - implementation behaves as though the Svade extension were not implemented for S-mode address - translation. - - When the hypervisor extension is implemented, if ADUE=1, hardware updating of PTE A/D bits - is enabled during G-stage address translation, and the implementation behaves as though the - Svade extension were not implemented for G-stage address translation. When ADUE=0, the - implementation behaves as though Svade were implemented for S-mode and - G-stage address translation. - - If Svadu is not implemented, ADUE is read-only zero. - - Furthermore, for implementations with the hypervisor extension, henvcfg.ADUE is read-only - zero if menvcfg.ADUE is zero. - definedBy: Svadu - type(): | - return (implemented?(ExtensionName::Svadu)) ? CsrFieldType::RO : CsrFieldType::RW; - reset_value(): | - return (implemented?(ExtensionName::Svadu)) ? UNDEFINED_LEGAL : 0; - CBZE: - location: 7 - description: | - *Cache Block Zero instruction Enable* - - Enables the execution of the cache block zero instruction, `CBO.ZERO`, - <% if ext?(:S) %> - in S-mode - <% elsif ext?(:U) %> - in U-mode - <% end %>. - - * `0`: The instruction raises an illegal instruction or virtual instruction exception - * `1`: The instruction is executed - - definedBy: Zicboz - type: RW - reset_value: UNDEFINED_LEGAL - CBCFE: - location: 6 - description: | - *Cache Block Clean and Flush instruction Enable* - - Enables the execution of the cache block clean instruction, `CBO.CLEAN`, and the - cache block flush instruction, `CBO.FLUSH`, - <% if ext?(:S) %> - in S-mode - <% elsif ext?(:U) %> - in U-mode - <% end %>. - - * `0`: The instruction raises an illegal instruction or virtual instruction exception - * `1`: The instruction is executed - - definedBy: Zicbom - type: RW - reset_value: UNDEFINED_LEGAL - CBIE: - location: 5-4 - description: | - *Cache Block Invalidate instruction Enable* - - Enables the execution of the cache block invalidate instruction, `CBO.INVAL`, - <% if ext?(:S) %> - in S-mode - <% elsif ext?(:U) %> - in U-mode - <% end %>. - - * `00`: The instruction raises an illegal instruction or virtual instruction exception - * `01`: The instruction is executed and performs a flush operation - * `10`: _Reserved_ - * `11`: The instruction is executed and performs an invalidate operation - definedBy: Zicbom - type: RW-R - sw_write(csr_value): | - if ((csr_value.CBIE == 0) || - (csr_value.CBIE == 1) || - ((!FORCE_UPGRADE_CBO_INVAL_TO_FLUSH) && (csr_value.CBIE == 3))) { - return csr_value.CBIE; - } else { - return CSR[menvcfg].CBIE; - } - reset_value: UNDEFINED_LEGAL - FIOM: - location: 0 - description: | - *Fence of I/O implies Memory* - - When `menvcfg.FIOM` is set, - FENCE instructions ordering I/O regions also implicitly order memory regions when executed - in any mode less privileged than M-mode. - - [separator="!",%autowidth,float="center",align="center",cols="^,<",options="header"] - !=== - !Instruction bit !Meaning when set - !PI + - PO - !Predecessor device input and memory reads (PR implied) + - Predecessor device output and memory writes (PW implied) - !SI + - SO - !Successor device input and memory reads (SR implied) + - Successor device output and memory writes (SW implied) - !=== - - Similarly, for modes less privileged than M when FIOM=1, if an atomic - instruction that accesses a region ordered as device I/O has its _aq_ - and/or _rl_ bit set, then that instruction is ordered as though it - accesses both device I/O and memory. - - type: RW - reset_value: UNDEFINED_LEGAL +$schema: "csr_schema.json#" +kind: csr +name: menvcfg +address: 0x30A +long_name: Machine Environment Configuration +description: | + Contains bits to enable/disable extensions + + The `menvcfg` CSR controls + certain characteristics of the execution environment for modes less + privileged than M. + + If bit FIOM (Fence of I/O implies Memory) is set to one in `menvcfg`, + FENCE instructions executed in modes less privileged than M are modified + so the requirement to order accesses to device I/O implies also the + requirement to order main memory accesses. <> + details the modified interpretation of FENCE instruction bits PI, PO, + SI, and SO for modes less privileged than M when FIOM=1. + + Similarly, for modes less privileged than M when FIOM=1, if an atomic + instruction that accesses a region ordered as device I/O has its _aq_ + and/or _rl_ bit set, then that instruction is ordered as though it + accesses both device I/O and memory. + + If S-mode is not supported, or if `satp`.MODE is read-only zero (always + Bare), the implementation may make FIOM read-only zero. + + [[menvcfg-FIOM]] + .Modified interpretation of FENCE predecessor and successor sets for modes less privileged than M when FIOM=1. + [separator="!",%autowidth,float="center",align="center",cols="^,<",options="header"] + !=== + !Instruction bit |Meaning when set + !PI + + PO + !Predecessor device input and memory reads (PR implied) + + Predecessor device output and memory writes (PW implied) + !SI + + SO + !Successor device input and memory reads (SR implied) + + Successor device output and memory writes (SW implied) + !=== + + [NOTE] + ==== + Bit FIOM is needed in `menvcfg` so M-mode can emulate the `H` (hypervisor) + extension, which has an + equivalent FIOM bit in the hypervisor CSR `henvcfg`. + ==== + + The PBMTE bit controls whether the Svpbmt extension is available for use + in S-mode and G-stage address translation (i.e., for page tables pointed + to by `satp` or `hgatp`). When PBMTE=1, Svpbmt is available for S-mode + and G-stage address translation. When PBMTE=0, the implementation + behaves as though Svpbmt were not implemented. If Svpbmt is not + implemented, PBMTE is read-only zero. Furthermore, for implementations + with the hypervisor extension, `henvcfg`.PBMTE is read-only zero if + `menvcfg`.PBMTE is zero. + + After changing `menvcfg`.PBMTE, executing an SFENCE.VMA instruction with + _rs1_=`x0` and _rs2_=`x0` suffices to synchronize address-translation caches + with respect to the altered interpretation of page-table entries' PBMT fields. + See <> for additional synchronization requirements when the + hypervisor extension is implemented. + + If the Svadu extension is implemented, the ADUE bit controls whether hardware + updating of PTE A/D bits is enabled for S-mode and G-stage address + translations. + When ADUE=1, hardware updating of PTE A/D bits is enabled during S-mode + address translation, and the implementation behaves as though the Svade + extension were not implemented for S-mode address translation. + When the hypervisor extension is implemented, if ADUE=1, hardware updating of + PTE A/D bits is enabled during G-stage address translation, and the + implementation behaves as though the Svade extension were not implemented for + G-stage address translation. + When ADUE=0, the implementation behaves as though Svade were implemented for + S-mode and G-stage address translation. + If Svadu is not implemented, ADUE is read-only zero. + Furthermore, for implementations with the hypervisor extension, `henvcfg`.ADUE + is read-only zero if `menvcfg`.ADUE is zero. + + NOTE: The Svade extension requires page-fault exceptions be raised when PTE + A/D bits need be set, hence Svade is implemented when ADUE=0. + + If the Smcdeleg extension is implemented, the CDE (Counter Delegation Enable) bit controls whether Zicntr and Zihpm counters can be delegated to S-mode. When CDE=1, the Smcdeleg extension is enabled, see <>. When CDE=0, the Smcdeleg and Ssccfg extensions appear to be not implemented. If Smcdeleg is not implemented, CDE is read-only zero. + + The definition of the STCE field is furnished by the Sstc extension. + + The definition of the CBZE field is furnished by the Zicboz extension. + + The definitions of the CBCFE and CBIE fields are furnished by the Zicbom extension. + + The definition of the PMM field will be furnished by the forthcoming + Smnpm extension. Its allocation within `menvcfg` may change prior to the + ratification of that extension. + + The Zicfilp extension adds the `LPE` field in `menvcfg`. When the `LPE` field is + set to 1 and S-mode is implemented, the Zicfilp extension is enabled in S-mode. + If `LPE` field is set to 1 and S-mode is not implemented, the Zicfilp extension + is enabled in U-mode. When the `LPE` field is 0, the Zicfilp extension is not + enabled in S-mode, and the following rules apply to S-mode. If the `LPE` field + is 0 and S-mode is not implemented, then the same rules apply to U-mode. + + * The hart does not update the `ELP` state; it remains as `NO_LP_EXPECTED`. + * The `LPAD` instruction operates as a no-op. + + The Zicfiss extension adds the `SSE` field to `menvcfg`. When the `SSE` field is + set to 1 the Zicfiss extension is activated in S-mode. When `SSE` field is 0, + the following rules apply to privilege modes that are less than M: + + * 32-bit Zicfiss instructions will revert to their behavior as defined by Zimop. + * 16-bit Zicfiss instructions will revert to their behavior as defined by Zcmop. + * The `pte.xwr=010b` encoding in VS/S-stage page tables becomes reserved. + * The `henvcfg.SSE` and `senvcfg.SSE` fields will read as zero and are read-only. + * `SSAMOSWAP.W/D` raises an illegal-instruction exception. + + The Ssdbltrp extension adds the double-trap-enable (`DTE`) field in `menvcfg`. + When `menvcfg.DTE` is zero, the implementation behaves as though Ssdbltrp is not + implemented. When Ssdbltrp is not implemented `sstatus.SDT`, `vsstatus.SDT`, and + `henvcfg.DTE` bits are read-only zero. + + When XLEN=32, `menvcfgh` is a 32-bit read/write register + that aliases bits 63:32 of `menvcfg`. + The `menvcfgh` register does not exist when XLEN=64. + + If U-mode is not supported, then registers `menvcfg` and `menvcfgh` do + not exist. +priv_mode: M +length: 64 +definedBy: + allOf: + - name: Sm + version: ">=1.12" + - name: U +fields: + STCE: + location: 63 + description: | + *STimecmp Enable* + + When set, `stimecmp` is operational. + + When clear, `stimecmp` access in a mode other than M-mode raises an `Illegal Instruction` trap. + S-mode timer interrupts will not be generated when clear, and `mip` and `sip` revert to their prior behavior without `Sstc`. + definedBy: Sstc + type: RW + reset_value: UNDEFINED_LEGAL + PBMTE: + location: 62 + description: | + *Page Based Memory Type Enable* + + The PBMTE bit controls whether the Svpbmt extension is available for use in S-mode<% if ext?(:H) %>and G-stage<% end %> + address translation (i.e., for page tables pointed to by satp<% if ext?(:H) %> or hgatp<% end %>). When PBMTE=1, Svpbmt is + available for S-mode <% if ext?(:H) %> and G-stage <% end %> address translation. When PBMTE=0, the implementation behaves + as though Svpbmt were not implemented. If Svpbmt is not implemented, PBMTE is read-only zero. + + <% if ext?(:H) %> + Furthermore, henvcfg.PBMTE is read-only zero if + menvcfg.PBMTE is zero. + <% end %> + + After changing `menvcfg.PBMTE`, executing an `sfence.vma` instruction with _rs1_=_x0_ and + _rs2_=_x0_ suffices to synchronize address-translation caches with respect to the altered + interpretation of page-table entries' PBMT fields. + + definedBy: Svpbmt + type: RW + reset_value: UNDEFINED_LEGAL + ADUE: + location: 61 + description: | + If the Svadu extension is implemented, the ADUE bit controls whether hardware updating of + PTE A/D bits is enabled for S-mode and G-stage address translations. When ADUE=1, hardware + updating of PTE A/D bits is enabled during S-mode address translation, and the + implementation behaves as though the Svade extension were not implemented for S-mode address + translation. + + When the hypervisor extension is implemented, if ADUE=1, hardware updating of PTE A/D bits + is enabled during G-stage address translation, and the implementation behaves as though the + Svade extension were not implemented for G-stage address translation. When ADUE=0, the + implementation behaves as though Svade were implemented for S-mode and + G-stage address translation. + + If Svadu is not implemented, ADUE is read-only zero. + + Furthermore, for implementations with the hypervisor extension, henvcfg.ADUE is read-only + zero if menvcfg.ADUE is zero. + definedBy: Svadu + type(): | + return (implemented?(ExtensionName::Svadu)) ? CsrFieldType::RO : CsrFieldType::RW; + reset_value(): | + return (implemented?(ExtensionName::Svadu)) ? UNDEFINED_LEGAL : 0; + CBZE: + location: 7 + description: | + *Cache Block Zero instruction Enable* + + Enables the execution of the cache block zero instruction, `CBO.ZERO`, + <% if ext?(:S) %> + in S-mode + <% elsif ext?(:U) %> + in U-mode + <% end %>. + + * `0`: The instruction raises an illegal instruction or virtual instruction exception + * `1`: The instruction is executed + + definedBy: Zicboz + type: RW + reset_value: UNDEFINED_LEGAL + CBCFE: + location: 6 + description: | + *Cache Block Clean and Flush instruction Enable* + + Enables the execution of the cache block clean instruction, `CBO.CLEAN`, and the + cache block flush instruction, `CBO.FLUSH`, + <% if ext?(:S) %> + in S-mode + <% elsif ext?(:U) %> + in U-mode + <% end %>. + + * `0`: The instruction raises an illegal instruction or virtual instruction exception + * `1`: The instruction is executed + + definedBy: Zicbom + type: RW + reset_value: UNDEFINED_LEGAL + CBIE: + location: 5-4 + description: | + *Cache Block Invalidate instruction Enable* + + Enables the execution of the cache block invalidate instruction, `CBO.INVAL`, + <% if ext?(:S) %> + in S-mode + <% elsif ext?(:U) %> + in U-mode + <% end %>. + + * `00`: The instruction raises an illegal instruction or virtual instruction exception + * `01`: The instruction is executed and performs a flush operation + * `10`: _Reserved_ + * `11`: The instruction is executed and performs an invalidate operation + definedBy: Zicbom + type: RW-R + sw_write(csr_value): | + if ((csr_value.CBIE == 0) || + (csr_value.CBIE == 1) || + ((!FORCE_UPGRADE_CBO_INVAL_TO_FLUSH) && (csr_value.CBIE == 3))) { + return csr_value.CBIE; + } else { + return CSR[menvcfg].CBIE; + } + reset_value: UNDEFINED_LEGAL + FIOM: + location: 0 + description: | + *Fence of I/O implies Memory* + + When `menvcfg.FIOM` is set, + FENCE instructions ordering I/O regions also implicitly order memory regions when executed + in any mode less privileged than M-mode. + + [separator="!",%autowidth,float="center",align="center",cols="^,<",options="header"] + !=== + !Instruction bit !Meaning when set + !PI + + PO + !Predecessor device input and memory reads (PR implied) + + Predecessor device output and memory writes (PW implied) + !SI + + SO + !Successor device input and memory reads (SR implied) + + Successor device output and memory writes (SW implied) + !=== + + Similarly, for modes less privileged than M when FIOM=1, if an atomic + instruction that accesses a region ordered as device I/O has its _aq_ + and/or _rl_ bit set, then that instruction is ordered as though it + accesses both device I/O and memory. + + type: RW + reset_value: UNDEFINED_LEGAL diff --git a/arch/csr/menvcfgh.yaml b/arch/csr/menvcfgh.yaml index 0062fae50..20e5308c0 100644 --- a/arch/csr/menvcfgh.yaml +++ b/arch/csr/menvcfgh.yaml @@ -1,44 +1,46 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -menvcfgh: - address: 0x31A - long_name: Machine Environment Configuration - description: Contains bits to enable/disable extensions - priv_mode: M - length: 32 - definedBy: - allOf: - - name: Sm - version: ">=1.12" - - name: U - fields: - STCE: - location: 31 - alias: menvcfg.STCE - description: | - *STimecmp Enable* - - Alias of `menvcfg.STCE` - definedBy: Sstc - type: RW - reset_value: UNDEFINED_LEGAL - PBMTE: - location: 30 - alias: menvcfg.PBMTE - description: | - *Page Based Memory Type Enable* +$schema: "csr_schema.json#" +kind: csr +name: menvcfgh +address: 0x31A +long_name: Machine Environment Configuration +description: Contains bits to enable/disable extensions +priv_mode: M +length: 32 +definedBy: + allOf: + - name: Sm + version: ">=1.12" + - name: U +fields: + STCE: + location: 31 + alias: menvcfg.STCE + description: | + *STimecmp Enable* + + Alias of `menvcfg.STCE` + definedBy: Sstc + type: RW + reset_value: UNDEFINED_LEGAL + PBMTE: + location: 30 + alias: menvcfg.PBMTE + description: | + *Page Based Memory Type Enable* - Alias of `menvcfg.PBMTE` - definedBy: Svpbmt - type: RW - reset_value: UNDEFINED_LEGAL - ADUE: - location: 29 - alias: menvcfg.ADUE - description: | - Alias of `menvcfg.ADUE` - definedBy: Svadu - type(): | - return (implemented?(ExtensionName::Svadu)) ? CsrFieldType::RO : CsrFieldType::RW; - reset_value(): | - return (implemented?(ExtensionName::Svadu)) ? UNDEFINED_LEGAL : 0; \ No newline at end of file + Alias of `menvcfg.PBMTE` + definedBy: Svpbmt + type: RW + reset_value: UNDEFINED_LEGAL + ADUE: + location: 29 + alias: menvcfg.ADUE + description: | + Alias of `menvcfg.ADUE` + definedBy: Svadu + type(): | + return (implemented?(ExtensionName::Svadu)) ? CsrFieldType::RO : CsrFieldType::RW; + reset_value(): | + return (implemented?(ExtensionName::Svadu)) ? UNDEFINED_LEGAL : 0; \ No newline at end of file diff --git a/arch/csr/mepc.yaml b/arch/csr/mepc.yaml index dc0d3a126..7d291543d 100644 --- a/arch/csr/mepc.yaml +++ b/arch/csr/mepc.yaml @@ -1,46 +1,48 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mepc: - long_name: Machine Exception Program Counter - address: 0x341 - priv_mode: M - length: MXLEN - description: | - Written with the PC of an instruction on an exception or interrupt taken in M-mode. +$schema: "csr_schema.json#" +kind: csr +name: mepc +long_name: Machine Exception Program Counter +address: 0x341 +priv_mode: M +length: MXLEN +description: | + Written with the PC of an instruction on an exception or interrupt taken in M-mode. - Also controls where the hart jumps on an exception return from M-mode. - definedBy: Sm - fields: - PC: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - When a trap is taken into M-mode, `mepc.PC` is written with the virtual address of the - instruction that was interrupted or that encountered the exception. - Otherwise, `mepc.PC` is never written by the implementation, though it may be explicitly written - by software. + Also controls where the hart jumps on an exception return from M-mode. +definedBy: Sm +fields: + PC: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + When a trap is taken into M-mode, `mepc.PC` is written with the virtual address of the + instruction that was interrupted or that encountered the exception. + Otherwise, `mepc.PC` is never written by the implementation, though it may be explicitly written + by software. - On an exception retun from M-mode (from the MRET instruction), - control transfers to the virtual address read out of `mepc.PC`. + On an exception retun from M-mode (from the MRET instruction), + control transfers to the virtual address read out of `mepc.PC`. - [when,"ext?(:C)"] - Because PCs are always halfword-aligned, bit 0 of `mepc.PC` is always - read-only 0. + [when,"ext?(:C)"] + Because PCs are always halfword-aligned, bit 0 of `mepc.PC` is always + read-only 0. - [when,"!ext?(:C)"] - Because PCs are always word-aligned, bits 1:0 of `mepc.PC` are always - read-only 0. + [when,"!ext?(:C)"] + Because PCs are always word-aligned, bits 1:0 of `mepc.PC` are always + read-only 0. - [when,"ext?(:C) && MUTABLE_MISA_C == true"] - When `misa.C` is clear, bit 1 is masked to zero. Writes to bit 1 are still captured, and - may be visible on the next read with `misa.C` is set. - type: RW-RH - sw_write(csr_value): | - return csr_value.PC & ~64'b1; - reset_value: 0 - sw_read(): | - if (implemented?(ExtensionName::C) && CSR[misa].C == 1'b1) { - return CSR[mepc].PC & ~64'b1; - } else { - return CSR[mepc].PC; - } \ No newline at end of file + [when,"ext?(:C) && MUTABLE_MISA_C == true"] + When `misa.C` is clear, bit 1 is masked to zero. Writes to bit 1 are still captured, and + may be visible on the next read with `misa.C` is set. + type: RW-RH + sw_write(csr_value): | + return csr_value.PC & ~64'b1; + reset_value: 0 +sw_read(): | + if (implemented?(ExtensionName::C) && CSR[misa].C == 1'b1) { + return CSR[mepc].PC & ~64'b1; + } else { + return CSR[mepc].PC; + } \ No newline at end of file diff --git a/arch/csr/mhartid.yaml b/arch/csr/mhartid.yaml index b3454d1de..1e5425801 100644 --- a/arch/csr/mhartid.yaml +++ b/arch/csr/mhartid.yaml @@ -1,18 +1,20 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mhartid: - long_name: Machine Hart ID - address: 0xf14 - priv_mode: M - length: MXLEN - description: Reports the unique hart-specific ID in the system. - definedBy: Sm - fields: - ID: - location_rv32: 31-0 - location_rv64: 63-0 - type: RO - description: hart-specific ID. - reset_value: UNDEFINED_LEGAL - sw_read(): | - return hartid(); +$schema: "csr_schema.json#" +kind: csr +name: mhartid +long_name: Machine Hart ID +address: 0xf14 +priv_mode: M +length: MXLEN +description: Reports the unique hart-specific ID in the system. +definedBy: Sm +fields: + ID: + location_rv32: 31-0 + location_rv64: 63-0 + type: RO + description: hart-specific ID. + reset_value: UNDEFINED_LEGAL +sw_read(): | + return hartid(); \ No newline at end of file diff --git a/arch/csr/mideleg.yaml b/arch/csr/mideleg.yaml index c72f8dfad..c8d408f1d 100644 --- a/arch/csr/mideleg.yaml +++ b/arch/csr/mideleg.yaml @@ -1,187 +1,189 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mideleg: - long_name: Machine Interrupt Delegation - address: 0x303 - priv_mode: M - length: MXLEN - definedBy: - # after 1.9.1, mideleg does not exist whe S-mode is not implemented - # we can represent that by making mideleg an S extension CSR post 1.9.1 - oneOf: +$schema: "csr_schema.json#" +kind: csr +name: mideleg +long_name: Machine Interrupt Delegation +address: 0x303 +priv_mode: M +length: MXLEN +definedBy: + # after 1.9.1, mideleg does not exist whe S-mode is not implemented + # we can represent that by making mideleg an S extension CSR post 1.9.1 + oneOf: + - name: Sm + version: "<= 1.9.1" + - allOf: + - name: S + version: "> 1.9.1" - name: Sm - version: "<= 1.9.1" - - allOf: - - name: S - version: "> 1.9.1" - - name: Sm - version: "> 1.9.1" - description: | - Controls exception delegation from M-mode to HS/S-mode - - By default, all traps at any privilege level are handled in machine - mode, though a machine-mode handler can redirect traps back to the - appropriate level with the `MRET` instruction. To increase performance, - implementations can provide individual read/write bits within `mideleg` - to indicate that certain exceptions and interrupts should - be processed directly by a lower privilege level. - - In harts with S-mode, the `mideleg` register must - exist, and setting a bit `mideleg` will delegate the - corresponding trap, when occurring in S-mode or U-mode, to the S-mode - trap handler - <%- if ext?(:H) -%> - (which could further be delegated to VS-mode through hideleg) - <%- end -%> - . - <%- if ext?(:S, "> 1.9.1") -%> - In harts without S-mode, the `mideleg` register should not exist. - - [NOTE] - ==== - In versions 1.9.1 and earlier , this register existed but was - hardwired to zero in M-mode only, or M/U without N harts. There is no - reason to require they return zero in those cases, as the `misa` - register indicates whether they exist. - ==== - <%- else -%> - In harts without S-mode, the `mideleg` register is read-only zero. - <%- end -%> - - An implementation can choose to subset the delegatable traps, with the - supported delegatable bits found by writing one to every bit location, - then reading back the value in `mideleg` to see which bit - positions hold a one. - - [NOTE] - ==== - Version 1.11 and earlier prohibited having any bits of `mideleg` be - read-only one. Platform standards may always add such restrictions. - ==== - - Traps never transition from a more-privileged mode to a less-privileged - mode. For example, if M-mode has delegated illegal-instruction - exceptions to S-mode, and M-mode software later executes an illegal - instruction, the trap is taken in M-mode, rather than being delegated to - S-mode. By contrast, traps may be taken horizontally. Using the same - example, if M-mode has delegated illegal-instruction exceptions to - S-mode, and S-mode software later executes an illegal instruction, the - trap is taken in S-mode. - - Delegated interrupts result in the interrupt being masked at the - delegator privilege level. For example, if the supervisor timer - interrupt (STI) is delegated to S-mode by setting `mideleg`[5], STIs - will not be taken when executing in M-mode. By contrast, if `mideleg`[5] - is clear, STIs can be taken in any mode and regardless of current mode - will transfer control to M-mode. - - `mideleg` holds trap delegation bits for individual interrupts, with the - layout of bits matching those in the `mip` register (i.e., STIP - interrupt delegation control is located in bit 5). - - For exceptions that cannot occur in less privileged modes, the - corresponding `medeleg` bits should be read-only zero. In particular, - `medeleg`[11] is read-only zero. - - <%- if ext?(:Smdbltrp) || ext?(:Ssdbltrp) -%> - The `medeleg`[16] is read-only zero as double trap is not delegatable. - <%- end -%> - - fields: - SSI: - location: 1 - description: | - *Supervisor Software Interrupt delegation* - - When 1, Supervisor Software interrupts are delegated to HS/S-mode. - type: RW - reset_value: 0 - VSSI: - location: 2 - description: | - *Virtual Supervisor Software Interrupt delegation* - - When 1, Virtual Supervisor Software interrupts are delegated to HS-mode. - - Virtual Supervisor Software Interrupts are always delegated to HS-mode, so this field is read-only one. - type: RO - reset_value: 1 - definedBy: H - MSI: - location: 3 - description: | - *Machine Software interrupt delegation* - - Since M-mode interrupts cannot be delegated, this field is read-only zero. - type: RO - reset_value: 0 - STI: - location: 5 - description: | - *Supervisor Timer interrupt delegation* + version: "> 1.9.1" +description: | + Controls exception delegation from M-mode to HS/S-mode + + By default, all traps at any privilege level are handled in machine + mode, though a machine-mode handler can redirect traps back to the + appropriate level with the `MRET` instruction. To increase performance, + implementations can provide individual read/write bits within `mideleg` + to indicate that certain exceptions and interrupts should + be processed directly by a lower privilege level. + + In harts with S-mode, the `mideleg` register must + exist, and setting a bit `mideleg` will delegate the + corresponding trap, when occurring in S-mode or U-mode, to the S-mode + trap handler + <%- if ext?(:H) -%> + (which could further be delegated to VS-mode through hideleg) + <%- end -%> + . + <%- if ext?(:S, "> 1.9.1") -%> + In harts without S-mode, the `mideleg` register should not exist. + + [NOTE] + ==== + In versions 1.9.1 and earlier , this register existed but was + hardwired to zero in M-mode only, or M/U without N harts. There is no + reason to require they return zero in those cases, as the `misa` + register indicates whether they exist. + ==== + <%- else -%> + In harts without S-mode, the `mideleg` register is read-only zero. + <%- end -%> + + An implementation can choose to subset the delegatable traps, with the + supported delegatable bits found by writing one to every bit location, + then reading back the value in `mideleg` to see which bit + positions hold a one. + + [NOTE] + ==== + Version 1.11 and earlier prohibited having any bits of `mideleg` be + read-only one. Platform standards may always add such restrictions. + ==== + + Traps never transition from a more-privileged mode to a less-privileged + mode. For example, if M-mode has delegated illegal-instruction + exceptions to S-mode, and M-mode software later executes an illegal + instruction, the trap is taken in M-mode, rather than being delegated to + S-mode. By contrast, traps may be taken horizontally. Using the same + example, if M-mode has delegated illegal-instruction exceptions to + S-mode, and S-mode software later executes an illegal instruction, the + trap is taken in S-mode. + + Delegated interrupts result in the interrupt being masked at the + delegator privilege level. For example, if the supervisor timer + interrupt (STI) is delegated to S-mode by setting `mideleg`[5], STIs + will not be taken when executing in M-mode. By contrast, if `mideleg`[5] + is clear, STIs can be taken in any mode and regardless of current mode + will transfer control to M-mode. + + `mideleg` holds trap delegation bits for individual interrupts, with the + layout of bits matching those in the `mip` register (i.e., STIP + interrupt delegation control is located in bit 5). + + For exceptions that cannot occur in less privileged modes, the + corresponding `medeleg` bits should be read-only zero. In particular, + `medeleg`[11] is read-only zero. + + <%- if ext?(:Smdbltrp) || ext?(:Ssdbltrp) -%> + The `medeleg`[16] is read-only zero as double trap is not delegatable. + <%- end -%> + +fields: + SSI: + location: 1 + description: | + *Supervisor Software Interrupt delegation* + + When 1, Supervisor Software interrupts are delegated to HS/S-mode. + type: RW + reset_value: 0 + VSSI: + location: 2 + description: | + *Virtual Supervisor Software Interrupt delegation* + + When 1, Virtual Supervisor Software interrupts are delegated to HS-mode. - When 1, Supervisor Timer interrupts are delegated to HS/S-mode. - type: RW - reset_value: 0 - VSTI: - location: 6 - description: | - *Virutal Supervisor Timer interrupt delegation* - - When 1, Virtual Supervisor Timer interrupts are delegated to HS-mode. - - Virtual Supervisor Time Interrupts are always delegated to HS-mode, so this field is read-only one. - type: RO - reset_value: 1 - definedBy: H - MTI: - location: 7 - description: | - *Machine Timer interrupt delegation* - - Since M-mode interrupts cannot be delegated, this field is read-only zero. - type: RO - reset_value: 0 - SEI: - location: 9 - description: | - *Supervisor External interrupt delegation* + Virtual Supervisor Software Interrupts are always delegated to HS-mode, so this field is read-only one. + type: RO + reset_value: 1 + definedBy: H + MSI: + location: 3 + description: | + *Machine Software interrupt delegation* - When 1, Supervisor External interrupts are delegated to HS/S-mode. - type: RW - reset_value: 0 - VSEI: - location: 10 - description: | - *Virtual Supervisor External interrupt delegation* - - Virtual Supervisor External Interrupts are always delegated to HS-mode, so this field is read-only one. - type: RO - reset_value: 1 - definedBy: H - MEI: - location: 11 - description: | - *Machine External interrupt delegation* - - Since M-mode interrupts cannot be delegated, this field is read-only zero. - type: RO - reset_value: 0 - SGEI: - location: 12 - description: | - *Supervisor Guest External Interrupt delegation* - - Supervisor Guest External interrupts are always delegated to HS-mode, so this field is read-only one. - type: RO - reset_value: 1 - definedBy: H - LCOFI: - location: 13 - description: | - *Local Counter Overflow Interrupt delegation* - - When 1, local counter overflow interrupts are delegated to (H)S-mode. - type: RW - reset_value: 0 - definedBy: Sscofpmf + Since M-mode interrupts cannot be delegated, this field is read-only zero. + type: RO + reset_value: 0 + STI: + location: 5 + description: | + *Supervisor Timer interrupt delegation* + + When 1, Supervisor Timer interrupts are delegated to HS/S-mode. + type: RW + reset_value: 0 + VSTI: + location: 6 + description: | + *Virutal Supervisor Timer interrupt delegation* + + When 1, Virtual Supervisor Timer interrupts are delegated to HS-mode. + + Virtual Supervisor Time Interrupts are always delegated to HS-mode, so this field is read-only one. + type: RO + reset_value: 1 + definedBy: H + MTI: + location: 7 + description: | + *Machine Timer interrupt delegation* + + Since M-mode interrupts cannot be delegated, this field is read-only zero. + type: RO + reset_value: 0 + SEI: + location: 9 + description: | + *Supervisor External interrupt delegation* + + When 1, Supervisor External interrupts are delegated to HS/S-mode. + type: RW + reset_value: 0 + VSEI: + location: 10 + description: | + *Virtual Supervisor External interrupt delegation* + + Virtual Supervisor External Interrupts are always delegated to HS-mode, so this field is read-only one. + type: RO + reset_value: 1 + definedBy: H + MEI: + location: 11 + description: | + *Machine External interrupt delegation* + + Since M-mode interrupts cannot be delegated, this field is read-only zero. + type: RO + reset_value: 0 + SGEI: + location: 12 + description: | + *Supervisor Guest External Interrupt delegation* + + Supervisor Guest External interrupts are always delegated to HS-mode, so this field is read-only one. + type: RO + reset_value: 1 + definedBy: H + LCOFI: + location: 13 + description: | + *Local Counter Overflow Interrupt delegation* + + When 1, local counter overflow interrupts are delegated to (H)S-mode. + type: RW + reset_value: 0 + definedBy: Sscofpmf diff --git a/arch/csr/mie.yaml b/arch/csr/mie.yaml index 7445ab7e0..b4a6e8a98 100644 --- a/arch/csr/mie.yaml +++ b/arch/csr/mie.yaml @@ -1,134 +1,136 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mie: - long_name: Machine Interrupt Enable - address: 0x304 - priv_mode: M - length: MXLEN - definedBy: Sm - description: "$copy: mip.yaml#/mip/description" - fields: - SSIE: - location: 1 - alias: - - sie.SSIE - description: | - Enables Supervisor Software Interrupts. - - Alias of `sie.SSIE` when `mideleg.SSI` is set. Otherwise, `sie.SSIE` is read-only 0. - type: RW - definedBy: S - reset_value: 0 - VSSIE: - location: 2 - alias: - - hie.VSSIE - - vsie.SSIE - - sie.SSIE - description: | - Enables Virtual Supervisor Software Interrupts. - - Alias of `hie.VSSIE`. - - Alias of `vsie.SSIE` when `hideleg.VSSI` is set. Otherwise, `vseie.SSIE` is read-only 0. - - Alias of `sie.SSIE` when `hideleg.VSSI` is set and the current mode is VS or VU - (Because `mie` is inaccessible in VS or VU mode, this alias can never be observed by software). - type: RW - definedBy: H - reset_value: 0 - MSIE: - location: 3 - description: Enables Machine Software Interrupts. - type: RW - reset_value: 0 - STIE: - location: 5 - alias: sip.STIE - description: | - Enables Supervisor Timer Interrupts. - - Alias of `sip.STIE` when `mideleg.STI` is set. Otherwise, `sip.STIE` is read-only 0. - type: RW - definedBy: S - reset_value: 0 - VSTIE: - location: 6 - alias: - - hie.VSTIE - - vsie.STIE - - sie.STIE - description: | - Enables Virtual Supervisor Timer Interrupts. - - Alias of `hie.VSTIE`. - - Alias of `vsie.STIE` when `hideleg.VSTI` is set. Otherwise, `vseie.STIE` is read-only 0. - - Alias of `sie.STIE` when `hideleg.VSTI` is set and the current mode is VS or VU - (Because `mie` is inaccessible in VS or VU mode, this alias can never be observed by software). - type: RW - definedBy: H - reset_value: 0 - MTIE: - location: 7 - description: Enables Machine Timer Interrupts. - type: RW - reset_value: 0 - SEIE: - location: 9 - alias: sip.SEIE - description: | - Enables Supervisor External Interrupts. - - Alias of `sie.SEIE` when `mideleg.SEI` is set. Otherwise, `sie.SEIE` is read-only 0. - type: RW - definedBy: S - reset_value: 0 - VSEIE: - location: 10 - alias: - - hie.VSEIE - - vsie.SEIE - - sie.SEIE - description: | - Enables Virtual Supervisor External Interrupts. - - Alias of `hie.VSEIE`. - - Alias of `vsie.SEIE` when `hideleg.VSEI` is set. Otherwise, `vseie.SEIE` is read-only 0. - - Alias of `sie.SEIE` when `hideleg.VSEI` is set and the current mode is VS or VU - (Because `mie` is inaccessible in VS or VU mode, this alias can never be observed by software). - type: RW - definedBy: H - reset_value: 0 - MEIE: - location: 11 - description: Enables Machine External Interrupts. - type: RW - reset_value: 0 - SGEIE: - location: 12 - alias: hie.SGEIE - description: | - Enables Supervisor Guest External Interrupts - - Alias of `hie.SGEIE`. - type: RW - definedBy: H - reset_value: 0 - LCOFIE: - location: 13 - alias: - - sie.LCOFIE - - vsie.LCOFIE - description: | - Enables Local Counter Overflow Interrupts. - - Alias of `sie.LCOFIE` when `mideleg.LCOFI` is set. Otherwise, `sie.LCOFIE` is an independent writeable bit when `mvien.LCOFI` is set or is read-only 0. - - Alias of `vsip.LCOFIE` when `hideleg.LCOFI` is set. Otherwise, `vsip.LCOFIE` is read-only 0. - type: RW - definedBy: Sscofpmf - reset_value: 0 \ No newline at end of file +$schema: "csr_schema.json#" +kind: csr +name: mie +long_name: Machine Interrupt Enable +address: 0x304 +priv_mode: M +length: MXLEN +definedBy: Sm +description: "$copy: mip.yaml#/mip/description" +fields: + SSIE: + location: 1 + alias: + - sie.SSIE + description: | + Enables Supervisor Software Interrupts. + + Alias of `sie.SSIE` when `mideleg.SSI` is set. Otherwise, `sie.SSIE` is read-only 0. + type: RW + definedBy: S + reset_value: 0 + VSSIE: + location: 2 + alias: + - hie.VSSIE + - vsie.SSIE + - sie.SSIE + description: | + Enables Virtual Supervisor Software Interrupts. + + Alias of `hie.VSSIE`. + + Alias of `vsie.SSIE` when `hideleg.VSSI` is set. Otherwise, `vseie.SSIE` is read-only 0. + + Alias of `sie.SSIE` when `hideleg.VSSI` is set and the current mode is VS or VU + (Because `mie` is inaccessible in VS or VU mode, this alias can never be observed by software). + type: RW + definedBy: H + reset_value: 0 + MSIE: + location: 3 + description: Enables Machine Software Interrupts. + type: RW + reset_value: 0 + STIE: + location: 5 + alias: sip.STIE + description: | + Enables Supervisor Timer Interrupts. + + Alias of `sip.STIE` when `mideleg.STI` is set. Otherwise, `sip.STIE` is read-only 0. + type: RW + definedBy: S + reset_value: 0 + VSTIE: + location: 6 + alias: + - hie.VSTIE + - vsie.STIE + - sie.STIE + description: | + Enables Virtual Supervisor Timer Interrupts. + + Alias of `hie.VSTIE`. + + Alias of `vsie.STIE` when `hideleg.VSTI` is set. Otherwise, `vseie.STIE` is read-only 0. + + Alias of `sie.STIE` when `hideleg.VSTI` is set and the current mode is VS or VU + (Because `mie` is inaccessible in VS or VU mode, this alias can never be observed by software). + type: RW + definedBy: H + reset_value: 0 + MTIE: + location: 7 + description: Enables Machine Timer Interrupts. + type: RW + reset_value: 0 + SEIE: + location: 9 + alias: sip.SEIE + description: | + Enables Supervisor External Interrupts. + + Alias of `sie.SEIE` when `mideleg.SEI` is set. Otherwise, `sie.SEIE` is read-only 0. + type: RW + definedBy: S + reset_value: 0 + VSEIE: + location: 10 + alias: + - hie.VSEIE + - vsie.SEIE + - sie.SEIE + description: | + Enables Virtual Supervisor External Interrupts. + + Alias of `hie.VSEIE`. + + Alias of `vsie.SEIE` when `hideleg.VSEI` is set. Otherwise, `vseie.SEIE` is read-only 0. + + Alias of `sie.SEIE` when `hideleg.VSEI` is set and the current mode is VS or VU + (Because `mie` is inaccessible in VS or VU mode, this alias can never be observed by software). + type: RW + definedBy: H + reset_value: 0 + MEIE: + location: 11 + description: Enables Machine External Interrupts. + type: RW + reset_value: 0 + SGEIE: + location: 12 + alias: hie.SGEIE + description: | + Enables Supervisor Guest External Interrupts + + Alias of `hie.SGEIE`. + type: RW + definedBy: H + reset_value: 0 + LCOFIE: + location: 13 + alias: + - sie.LCOFIE + - vsie.LCOFIE + description: | + Enables Local Counter Overflow Interrupts. + + Alias of `sie.LCOFIE` when `mideleg.LCOFI` is set. Otherwise, `sie.LCOFIE` is an independent writeable bit when `mvien.LCOFI` is set or is read-only 0. + + Alias of `vsip.LCOFIE` when `hideleg.LCOFI` is set. Otherwise, `vsip.LCOFIE` is read-only 0. + type: RW + definedBy: Sscofpmf + reset_value: 0 \ No newline at end of file diff --git a/arch/csr/mimpid.yaml b/arch/csr/mimpid.yaml index 1b320b57c..228953b37 100644 --- a/arch/csr/mimpid.yaml +++ b/arch/csr/mimpid.yaml @@ -1,33 +1,35 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mimpid: - long_name: Machine Implementation ID - address: 0xf13 - priv_mode: M - length: MXLEN - description: | - Reports the vendor-specific implementation ID. +$schema: "csr_schema.json#" +kind: csr +name: mimpid +long_name: Machine Implementation ID +address: 0xf13 +priv_mode: M +length: MXLEN +description: | + Reports the vendor-specific implementation ID. - The `mimpid` CSR provides a unique encoding of the version of the - processor implementation. This register must be readable in any - implementation, but a value of 0 can be returned to indicate that the - field is not implemented. The Implementation value should reflect the - design of the RISC-V processor itself and not any surrounding system. + The `mimpid` CSR provides a unique encoding of the version of the + processor implementation. This register must be readable in any + implementation, but a value of 0 can be returned to indicate that the + field is not implemented. The Implementation value should reflect the + design of the RISC-V processor itself and not any surrounding system. - [NOTE] - ==== - The format of this field is left to the provider of the architecture - source code, but will often be printed by standard tools as a - hexadecimal string without any leading or trailing zeros, so the - Implementation value can be left-justified (i.e., filled in from - most-significant nibble down) with subfields aligned on nibble - boundaries to ease human readability. - ==== - definedBy: Sm - fields: - Implementation: - location_rv32: 31-0 - location_rv64: 63-0 - type: RO - description: Vendor-specific implementation ID. - reset_value(): return IMP_ID; \ No newline at end of file + [NOTE] + ==== + The format of this field is left to the provider of the architecture + source code, but will often be printed by standard tools as a + hexadecimal string without any leading or trailing zeros, so the + Implementation value can be left-justified (i.e., filled in from + most-significant nibble down) with subfields aligned on nibble + boundaries to ease human readability. + ==== +definedBy: Sm +fields: + Implementation: + location_rv32: 31-0 + location_rv64: 63-0 + type: RO + description: Vendor-specific implementation ID. + reset_value(): return IMP_ID; \ No newline at end of file diff --git a/arch/csr/minstret.yaml b/arch/csr/minstret.yaml index dac233929..9d4344a1c 100644 --- a/arch/csr/minstret.yaml +++ b/arch/csr/minstret.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -minstret: - long_name: Machine Instructions Retired Counter - address: 0xB02 - description: | - Counts the number of instructions retired by this hart from some arbitrary start point in the past. +$schema: "csr_schema.json#" +kind: csr +name: minstret +long_name: Machine Instructions Retired Counter +address: 0xB02 +description: | + Counts the number of instructions retired by this hart from some arbitrary start point in the past. - [NOTE] - Instructions that cause synchronous exceptions, including `ecall` and `ebreak`, are not - considered to retire and hence do not increment the `minstret` CSR. - priv_mode: M - length: 64 - fields: - COUNT: - location: 63-0 - type: RW-H - description: | - Instructions retired counter. + [NOTE] + Instructions that cause synchronous exceptions, including `ecall` and `ebreak`, are not + considered to retire and hence do not increment the `minstret` CSR. +priv_mode: M +length: 64 +fields: + COUNT: + location: 63-0 + type: RW-H + description: | + Instructions retired counter. - <%- if ext?(:Zicntr) -%> - Aliased as `instret.COUNT`. - <%- end -%> + <%- if ext?(:Zicntr) -%> + Aliased as `instret.COUNT`. + <%- end -%> - Increments every time an instruction retires unless: + Increments every time an instruction retires unless: - * `mcountinhibit.IR` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.IR`<%- end -%> is set - <%- if ext?(:Smcntrpmf) -%> - * `minstretcfg.MINH` is set and the current privilege level is M - <%- if ext?(:S) -%> - * `minstretcfg.SINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is (H)S - <%- end -%> - <%- if ext?(:U) -%> - * `minstretcfg.UINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is U - <%- end -%> - <%- if ext?(:H) -%> - * `minstretcfg.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is VS - * `minstretcfg.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is VU - <%- end -%> - <%- end -%> + * `mcountinhibit.IR` <%- if ext?(:Smcdeleg) -%>or its alias `scountinhibit.IR`<%- end -%> is set + <%- if ext?(:Smcntrpmf) -%> + * `minstretcfg.MINH` is set and the current privilege level is M + <%- if ext?(:S) -%> + * `minstretcfg.SINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is (H)S + <%- end -%> + <%- if ext?(:U) -%> + * `minstretcfg.UINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is U + <%- end -%> + <%- if ext?(:H) -%> + * `minstretcfg.VSINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is VS + * `minstretcfg.VUINH` <%- if ext?(:Ssccfg) -%>or its alias `instretcfg.SINH`<%- end -%> is set and the current privilege level is VU + <%- end -%> + <%- end -%> - An instruction that causes an exception, notably including MRET/SRET, - does not retire and does not cause `minstret.COUNT` to increment. - reset_value: UNDEFINED_LEGAL - affectedBy: [Zicntr, Smcntrpmf, Smcdeleg, Ssccfg] - definedBy: Zicntr - \ No newline at end of file + An instruction that causes an exception, notably including MRET/SRET, + does not retire and does not cause `minstret.COUNT` to increment. + reset_value: UNDEFINED_LEGAL + affectedBy: [Zicntr, Smcntrpmf, Smcdeleg, Ssccfg] +definedBy: Zicntr diff --git a/arch/csr/minstreth.yaml b/arch/csr/minstreth.yaml index e5a928dfb..0d3f71ccb 100644 --- a/arch/csr/minstreth.yaml +++ b/arch/csr/minstreth.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -minstreth: - long_name: Machine Instructions Retired Counter - address: 0xB02 - description: | - Upper half of 64-bit instructions retired counters. +$schema: "csr_schema.json#" +kind: csr +name: minstreth +long_name: Machine Instructions Retired Counter +address: 0xB02 +description: | + Upper half of 64-bit instructions retired counters. - See `minstret` for details. - priv_mode: M - length: 32 - fields: - COUNT: - alias: - - minstret.COUNT[63:32] - location: 31-0 - type: RW-H - description: | - *Instructions retired counter* + See `minstret` for details. +priv_mode: M +length: 32 +fields: + COUNT: + alias: + - minstret.COUNT[63:32] + location: 31-0 + type: RW-H + description: | + *Instructions retired counter* - Upper half of `minstret`. - reset_value: UNDEFINED_LEGAL - affectedBy: [Zicntr, Smcntrpmf, Smcdeleg, Ssccfg] - sw_write(csr_value): | - CSR[mcycle].COUNT = {csr_value.COUNT[31:0], CSR[minstret].COUNT[31:0]}; - return csr_value.COUNT; - definedBy: Zicntr - sw_read(): | - return CSR[minstret].COUNT[63:32]; \ No newline at end of file + Upper half of `minstret`. + reset_value: UNDEFINED_LEGAL + affectedBy: [Zicntr, Smcntrpmf, Smcdeleg, Ssccfg] + sw_write(csr_value): | + CSR[mcycle].COUNT = {csr_value.COUNT[31:0], CSR[minstret].COUNT[31:0]}; + return csr_value.COUNT; +definedBy: Zicntr +sw_read(): | + return CSR[minstret].COUNT[63:32]; \ No newline at end of file diff --git a/arch/csr/mip.yaml b/arch/csr/mip.yaml index 303635ba0..15b2367f7 100644 --- a/arch/csr/mip.yaml +++ b/arch/csr/mip.yaml @@ -1,396 +1,398 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mip: - long_name: Machine Interrupt Pending - address: 0x344 - priv_mode: M - description: | - The `mip` register is an MXLEN-bit read/write register containing - information on pending interrupts, while `mie` is the corresponding - MXLEN-bit read/write register containing interrupt enable bits. - Interrupt cause number _i_ (as reported in CSR `mcause`) - corresponds with bit _i_ in both `mip` and - `mie`. Bits 15:0 are allocated to standard interrupt causes only, while - bits 16 and above are designated for platform use. - - NOTE: Interrupts designated for platform use may be designated for custom use - at the platform's discretion. - - An interrupt _i_ will trap to M-mode (causing the privilege mode to - change to M-mode) if all of the following are true: - - * either the current privilege mode is M and the MIE bit in the `mstatus` register is - set, or the current privilege mode has less privilege than M-mode; - * bit _i_ is set in both `mip` and `mie` - * if register `mideleg` exists, bit _i_ is not set in `mideleg`. - - These conditions for an interrupt trap to occur must be evaluated in a - bounded amount of time from when an interrupt becomes, or ceases to be, - pending in `mip`, and must also be evaluated immediately following the - execution of an __x__RET instruction or an explicit write to a CSR on - which these interrupt trap conditions expressly depend (including `mip`, - `mie`, `mstatus`, and `mideleg`). - - Interrupts to M-mode take priority over any interrupts to lower - privilege modes. - - Each individual bit in register `mip` may be writable or may be - read-only. When bit _i_ in `mip` is writable, a pending interrupt _i_ - can be cleared by writing 0 to this bit. If interrupt _i_ can become - pending but bit _i_ in `mip` is read-only, the implementation must - provide some other mechanism for clearing the pending interrupt. - - A bit in `mie` must be writable if the corresponding interrupt can ever - become pending. Bits of `mie` that are not writable must be read-only - zero. - - [NOTE] - ==== - The machine-level interrupt registers handle a few root interrupt - sources which are assigned a fixed service priority for simplicity, - while separate external interrupt controllers can implement a more - complex prioritization scheme over a much larger set of interrupts that - are then muxed into the machine-level interrupt sources. - - ''' - - The non-maskable interrupt is not made visible via the `mip` register as - its presence is implicitly known when executing the NMI trap handler. - ==== - - If supervisor mode is implemented, bits `mip`.SEIP and `mie`.SEIE are - the interrupt-pending and interrupt-enable bits for supervisor-level - external interrupts. SEIP is writable in `mip`, and may be written by - M-mode software to indicate to S-mode that an external interrupt is - pending. Additionally, the platform-level interrupt controller may - generate supervisor-level external interrupts. Supervisor-level external - interrupts are made pending based on the logical-OR of the - software-writable SEIP bit and the signal from the external interrupt - controller. When `mip` is read with a CSR instruction, the value of the - SEIP bit returned in the `rd` destination register is the logical-OR of - the software-writable bit and the interrupt signal from the interrupt - controller, but the signal from the interrupt controller is not used to - calculate the value written to SEIP. Only the software-writable SEIP bit - participates in the read-modify-write sequence of a CSRRS or CSRRC - instruction. - - [NOTE] - ==== - For example, if we name the software-writable SEIP bit `B` and the - signal from the external interrupt controller `E`, then if - `csrrs t0, mip, t1` is executed, `t0[9]` is written with `B || E`, then - `B` is written with `B || t1[9]`. If `csrrw t0, mip, t1` is executed, - then `t0[9]` is written with `B || E`, and `B` is simply written with - `t1[9]`. In neither case does `B` depend upon `E`. - - The SEIP field behavior is designed to allow a higher privilege layer to - mimic external interrupts cleanly, without losing any real external - interrupts. The behavior of the CSR instructions is slightly modified - from regular CSR accesses as a result. - ==== - - If supervisor mode is implemented, bits `mip`.STIP and `mie`.STIE are - the interrupt-pending and interrupt-enable bits for supervisor-level - timer interrupts. STIP is writable in `mip`, and may be written by - M-mode software to deliver timer interrupts to S-mode. - - If supervisor mode is implemented, bits `mip`.SSIP and `mie`.SSIE are - the interrupt-pending and interrupt-enable bits for supervisor-level - software interrupts. SSIP is writable in `mip` and may also be set to 1 - by a platform-specific interrupt controller. - - <% if ext?(:Sscofpmf) -%> - bits `mip`.LCOFIP and `mie`.LCOFIE - are the interrupt-pending and interrupt-enable bits for local counter-overflow - interrupts. - LCOFIP is read-write in `mip` and reflects the occurrence of a local - counter-overflow overflow interrupt request resulting from any of the - `mhpmevent__n__`.OF bits being set. - <% end -%> - - Multiple simultaneous interrupts destined for M-mode are handled in the - following decreasing priority order: MEI, MSI, MTI, SEI, SSI, STI, LCOFI. - - [NOTE] - ==== - The machine-level interrupt fixed-priority ordering rules were developed - with the following rationale. - - Interrupts for higher privilege modes must be serviced before interrupts - for lower privilege modes to support preemption. - - The platform-specific machine-level interrupt sources in bits 16 and - above have platform-specific priority, but are typically chosen to have - the highest service priority to support very fast local vectored - interrupts. - - External interrupts are handled before internal (timer/software) - interrupts as external interrupts are usually generated by devices that - might require low interrupt service times. - - Software interrupts are handled before internal timer interrupts, - because internal timer interrupts are usually intended for time slicing, - where time precision is less important, whereas software interrupts are - used for inter-processor messaging. Software interrupts can be avoided - when high-precision timing is required, or high-precision timer - interrupts can be routed via a different interrupt path. Software - interrupts are located in the lowest four bits of `mip` as these are - often written by software, and this position allows the use of a single - CSR instruction with a five-bit immediate. - ==== - - Restricted views of the `mip` and `mie` registers appear as the `sip` - and `sie` registers for supervisor level. If an interrupt is delegated - to S-mode by setting a bit in the `mideleg` register, it becomes visible - in the `sip` register and is maskable using the `sie` register. - Otherwise, the corresponding bits in `sip` and `sie` are read-only zero. - length: MXLEN - definedBy: Sm - fields: - SSIP: - location: 1 - alias: - - sip.SSIP - - mvip.SSIP - description: | - *Supervisor Software Interrupt Pending* - - Reports the current pending state of an (H)S-mode software interrupt, which is generated by writing to this field. - - <%- if ext?(:Smaia) -%> - When using AIA/IMSIC, IPIs are expected to be delivered as external interrupts - and SSIP is not backed by any hardware update (aside from any aliasing effects). - However, SSIP is still writable by M-mode software and, when written, can be used to - generate an S-mode Software Interrupt. - <%- end -%> - - <% if ext?(:Smaia) %>_Aliases_<% else %>_Alias_<% end %>: - - * `sip.SSIP` when `mideleg.SSI` is set - <%- if ext?(:Smaia) -%> - * `mvip.SSIP` - <%- end -%> - type: RW - reset_value: 0 - definedBy: S - affectedBy: Smaia - VSSIP: - location: 2 - alias: - - hip.VSSIP - - hvip.VSSIP - - vsip.SSIP - - sip.SSIP - description: | - *Virtual Supervisor Software Interrupt Pending* - - Reports the current pending state of a VS-mode software interrupt, which is generated by writing to this field. - - <%- if ext?(:Smaia) -%> - When using AIA/IMSIC, IPIs are expected to be delivered as external interrupts and VSSIP is not backed by any hardware update (aside from any aliased writes). - However, VSSIP is still writable by M-mode software and, when written, can be used to - generate a VS-mode Software Interrupt. - <%- end -%> - - _Aliases_: - - * `hip.VSSIP` - * `hvip.VSSIP` - * `vsip.SSIP` when `hideleg.VSSI` is set - type: RW - reset_value: 0 - definedBy: H - affectedBy: Smaia - MSIP: - location: 3 - description: | - *Machine Software Interrupt Pending* - - Unused field. - - <%- if ext?(:Smaia) -%> - With AIA/IMSIC, IPIs are delievered as external interrupts. As a result, this bit is - unused and hardwired to 0. - <%- end -%> - type: RO - reset_value: 0 - STIP: - location: 5 - alias: - - sip.STIP - - mvip.STIP - description: | - *Supervisor Timer Interrupt Pending* - - Reports the current pending state of an (H)S-mode timer interrupt - <%- if ext?(:Sstc) -%> - , which is normally controlled by the `stimecmp` CSR. - <%- else -%> - , which is generated by software by writing to `mip.STIP`<% if ext?(:Smaia) %>or its alias `mvip.STIP`<% end %>. - <%- end -%> - - <%-if ext?(:Sstc) -%> - When `menvcfg.STCE` is set, `mip.STIP` is RO-H, and is completely controlled by the timer interrupt device (using `stimecmp`). - - When `menvcfg.STCE` is clear, `mip.STIP` is RW, and M-mode software may write the bit to inject a Supervisor Timer Interrupt. - <%- end -%> - - <% if ext?(:Smaia) %>_Aliases_<% else %>_Alias_<% end %>: - - * `sip.STIP` when `mideleg.STI` is set (though `sip.STIP` is a read-only view) - <%- if ext?(:Smaia) -%> - * `mvip.STIP` when when `menvcfg.STCE` is clear - <%- end -%> - - type: RW - reset_value: 0 - definedBy: S - affectedBy: Sstc - VSTIP: - location: 6 - alias: - - hip.VSTIP - description: | - *Virtual Supervisor Timer Interrupt Pending* - - Reports the current pending state of a VS-mode timer interrupt - <%- if ext?(:Sstc) -%> - , which is normally controlled by the `vstimecmp` CSR, but can also be injected by the hypervisor through `hvip.VSTIP`. - <%- else -%> - , which is generated by M-mode and/or HS-mode software by writing to `hvip.VSTIP`. - <%- end -%> - - <%-if ext?(:Sstc) -%> - When `menvcfg.STCE` is set (enabling the `Sstc` extension), `mip.VSTIP` is the logical OR of `hvip.VSTIP` and the VS-level interrupt signal generated by the timer device (controlled by the value of `vstimecmp`). - - When `menvcfg.STCE` is clear (disabling the `Sstc` extension), `mip.VSTIP` is exactly the value of `hvip.VSTIP`. - <%- end -%> - - `mip.VSTIP` is never writable. If VS-mode software wants to clear the bit, it must do so - <%- if ext?(:Sstc) -%> - by writing the `vstimecmp` register or - <%- end -%> - by calling into the hypervisor (which can then clear `hvip.VSTIP`). - - _Aliases_: - - * `hip.VSTIP` - * `vsip.STIP` when `hideleg.VSTI` is set - * `hvip.VSTIP` <% if ext?(:Sstc) %>when `menvcfg.STCE` is clear<% end %> (though `hvip.VSTIP` is writeable) - type: RO-H - reset_value: 0 - definedBy: H - affectedBy: Sstc - MTIP: - location: 7 - description: | - *Machine Timer Interrupt Pending* - - Reports the current pending state of an M-mode timer interrupt. - - Bit is controlled by the timer device (using `mtimecmp`), and is not writeable. - type: RO-H - reset_value: 0 - SEIP: - location: 9 - alias: - - sip.SEIP - description: | - *Supervisor External Interrupt Pending* - - Reports the current pending state of an (H)S-mode external interrupt. - - This field has two parts: a software-writeable shadow value and a wire from the interrupt controller. - The value presented to software in the bit on a CSR read is the logical OR of the software-writeable value and the interrupt controller value. - When software writes this bit, only the shadow value is updated (the interrupt controller is not notified of the write). - - <%- if ext?(:Smaia) -%> - The software-writeable shadow value is aliased in `mvip.SEIP` (`Smaia` extension). - <%- end -%> - - _Alias_: - - * `sip.SEIP` when `mideleg.SEI` is set (though `sip.SEIP` is read-only) - type: RW-H - definedBy: S - affectedBy: Smaia - reset_value: 0 - VSEIP: - location: 10 - alias: - - hip.VSEIP - - vsip.SEIP - - sip.SEIP - description: | - *Virtual Supervisor External Interrupt Pending* - - Reports the current pending state of a VS-mode external interrupt. - - This field is the logical OR of `hvip.VSEIP` and the wire coming from the interrupt controller. - - The field is not writable by software - <%- if ext?(:Smaia) -%> - (_i.e._, unlike the behavior of `mip.SEIP`/`mvip.SEIP`, attempted writes to `mip.VSEIP` do not propagate to `hvip.VSEIP`) - <%- end -%> - . - - _Aliases_: - - * `hip.VSEIP` - * `vsip.SEIP` when `hideleg.VSEI` is set - type: RO-H - reset_value: 0 - definedBy: H - affectedBy: Smaia - MEIP: - location: 11 - description: | - *Machine External Interrupt Pending* - - Reports the current pending state of an M-mode external interrupt. - - MEIP is controlled by the external interrupt controller <% if ext?(:Smaia) %>(AIA) <% end %>. - It is not writable by software. - type: RO-H - reset_value: 0 - SGEIP: - location: 12 - alias: hip.SGEIP - description: | - *Supervisor Guest External Interrupt Pending* - - Read-only summary of any pending Supervisor Guest External Interrupt Pending, i.e.: - the logical-OR reduction of the `hgeip` register. - - _Alias_: - - * `hip.SGEIP` - type: RO-H - reset_value: 0 - definedBy: H - LCOFIP: - location: 13 - alias: - - sip.LCOFIP - - vsip.LCOFIP - description: | - *Local Counter Overflow Interrupt pending* - - <%- if ext?(:H) -%> - When `hideleg.LCOFI` is set, - `vsip.LCOFIP`, `sip.LCOFIP`, and `mip.LCOFIP` are all aliases. - <%- end -%> - - When a counter overflow interrupt occurs, a hidden sticky bit is set. - - Software writes 0 to `mip.LCOFIP` to clear the pending interrupt. - - <% if ext?(:H) %>_Aliases_<% else %>_Alias_<% end %>: - - * `sip.LCOFIP` when `mideleg.LCOFI` is set - <%- if ext?(:H) -%> - * `vsip.LCOFIP` when `hideleg.LCOFI` is set - <%- end -%> - type: RW-H - reset_value: 0 - definedBy: Sscofpmf +$schema: "csr_schema.json#" +kind: csr +name: mip> +long_name: Machine Interrupt Pending +address: 0x344 +priv_mode: M +description: | + The `mip` register is an MXLEN-bit read/write register containing + information on pending interrupts, while `mie` is the corresponding + MXLEN-bit read/write register containing interrupt enable bits. + Interrupt cause number _i_ (as reported in CSR `mcause`) + corresponds with bit _i_ in both `mip` and + `mie`. Bits 15:0 are allocated to standard interrupt causes only, while + bits 16 and above are designated for platform use. + + NOTE: Interrupts designated for platform use may be designated for custom use + at the platform's discretion. + + An interrupt _i_ will trap to M-mode (causing the privilege mode to + change to M-mode) if all of the following are true: + + * either the current privilege mode is M and the MIE bit in the `mstatus` register is + set, or the current privilege mode has less privilege than M-mode; + * bit _i_ is set in both `mip` and `mie` + * if register `mideleg` exists, bit _i_ is not set in `mideleg`. + + These conditions for an interrupt trap to occur must be evaluated in a + bounded amount of time from when an interrupt becomes, or ceases to be, + pending in `mip`, and must also be evaluated immediately following the + execution of an __x__RET instruction or an explicit write to a CSR on + which these interrupt trap conditions expressly depend (including `mip`, + `mie`, `mstatus`, and `mideleg`). + + Interrupts to M-mode take priority over any interrupts to lower + privilege modes. + + Each individual bit in register `mip` may be writable or may be + read-only. When bit _i_ in `mip` is writable, a pending interrupt _i_ + can be cleared by writing 0 to this bit. If interrupt _i_ can become + pending but bit _i_ in `mip` is read-only, the implementation must + provide some other mechanism for clearing the pending interrupt. + + A bit in `mie` must be writable if the corresponding interrupt can ever + become pending. Bits of `mie` that are not writable must be read-only + zero. + + [NOTE] + ==== + The machine-level interrupt registers handle a few root interrupt + sources which are assigned a fixed service priority for simplicity, + while separate external interrupt controllers can implement a more + complex prioritization scheme over a much larger set of interrupts that + are then muxed into the machine-level interrupt sources. + + ''' + + The non-maskable interrupt is not made visible via the `mip` register as + its presence is implicitly known when executing the NMI trap handler. + ==== + + If supervisor mode is implemented, bits `mip`.SEIP and `mie`.SEIE are + the interrupt-pending and interrupt-enable bits for supervisor-level + external interrupts. SEIP is writable in `mip`, and may be written by + M-mode software to indicate to S-mode that an external interrupt is + pending. Additionally, the platform-level interrupt controller may + generate supervisor-level external interrupts. Supervisor-level external + interrupts are made pending based on the logical-OR of the + software-writable SEIP bit and the signal from the external interrupt + controller. When `mip` is read with a CSR instruction, the value of the + SEIP bit returned in the `rd` destination register is the logical-OR of + the software-writable bit and the interrupt signal from the interrupt + controller, but the signal from the interrupt controller is not used to + calculate the value written to SEIP. Only the software-writable SEIP bit + participates in the read-modify-write sequence of a CSRRS or CSRRC + instruction. + + [NOTE] + ==== + For example, if we name the software-writable SEIP bit `B` and the + signal from the external interrupt controller `E`, then if + `csrrs t0, mip, t1` is executed, `t0[9]` is written with `B || E`, then + `B` is written with `B || t1[9]`. If `csrrw t0, mip, t1` is executed, + then `t0[9]` is written with `B || E`, and `B` is simply written with + `t1[9]`. In neither case does `B` depend upon `E`. + + The SEIP field behavior is designed to allow a higher privilege layer to + mimic external interrupts cleanly, without losing any real external + interrupts. The behavior of the CSR instructions is slightly modified + from regular CSR accesses as a result. + ==== + + If supervisor mode is implemented, bits `mip`.STIP and `mie`.STIE are + the interrupt-pending and interrupt-enable bits for supervisor-level + timer interrupts. STIP is writable in `mip`, and may be written by + M-mode software to deliver timer interrupts to S-mode. + + If supervisor mode is implemented, bits `mip`.SSIP and `mie`.SSIE are + the interrupt-pending and interrupt-enable bits for supervisor-level + software interrupts. SSIP is writable in `mip` and may also be set to 1 + by a platform-specific interrupt controller. + + <% if ext?(:Sscofpmf) -%> + bits `mip`.LCOFIP and `mie`.LCOFIE + are the interrupt-pending and interrupt-enable bits for local counter-overflow + interrupts. + LCOFIP is read-write in `mip` and reflects the occurrence of a local + counter-overflow overflow interrupt request resulting from any of the + `mhpmevent__n__`.OF bits being set. + <% end -%> + + Multiple simultaneous interrupts destined for M-mode are handled in the + following decreasing priority order: MEI, MSI, MTI, SEI, SSI, STI, LCOFI. + + [NOTE] + ==== + The machine-level interrupt fixed-priority ordering rules were developed + with the following rationale. + + Interrupts for higher privilege modes must be serviced before interrupts + for lower privilege modes to support preemption. + + The platform-specific machine-level interrupt sources in bits 16 and + above have platform-specific priority, but are typically chosen to have + the highest service priority to support very fast local vectored + interrupts. + + External interrupts are handled before internal (timer/software) + interrupts as external interrupts are usually generated by devices that + might require low interrupt service times. + + Software interrupts are handled before internal timer interrupts, + because internal timer interrupts are usually intended for time slicing, + where time precision is less important, whereas software interrupts are + used for inter-processor messaging. Software interrupts can be avoided + when high-precision timing is required, or high-precision timer + interrupts can be routed via a different interrupt path. Software + interrupts are located in the lowest four bits of `mip` as these are + often written by software, and this position allows the use of a single + CSR instruction with a five-bit immediate. + ==== + + Restricted views of the `mip` and `mie` registers appear as the `sip` + and `sie` registers for supervisor level. If an interrupt is delegated + to S-mode by setting a bit in the `mideleg` register, it becomes visible + in the `sip` register and is maskable using the `sie` register. + Otherwise, the corresponding bits in `sip` and `sie` are read-only zero. +length: MXLEN +definedBy: Sm +fields: + SSIP: + location: 1 + alias: + - sip.SSIP + - mvip.SSIP + description: | + *Supervisor Software Interrupt Pending* + + Reports the current pending state of an (H)S-mode software interrupt, which is generated by writing to this field. + + <%- if ext?(:Smaia) -%> + When using AIA/IMSIC, IPIs are expected to be delivered as external interrupts + and SSIP is not backed by any hardware update (aside from any aliasing effects). + However, SSIP is still writable by M-mode software and, when written, can be used to + generate an S-mode Software Interrupt. + <%- end -%> + + <% if ext?(:Smaia) %>_Aliases_<% else %>_Alias_<% end %>: + + * `sip.SSIP` when `mideleg.SSI` is set + <%- if ext?(:Smaia) -%> + * `mvip.SSIP` + <%- end -%> + type: RW + reset_value: 0 + definedBy: S + affectedBy: Smaia + VSSIP: + location: 2 + alias: + - hip.VSSIP + - hvip.VSSIP + - vsip.SSIP + - sip.SSIP + description: | + *Virtual Supervisor Software Interrupt Pending* + + Reports the current pending state of a VS-mode software interrupt, which is generated by writing to this field. + + <%- if ext?(:Smaia) -%> + When using AIA/IMSIC, IPIs are expected to be delivered as external interrupts and VSSIP is not backed by any hardware update (aside from any aliased writes). + However, VSSIP is still writable by M-mode software and, when written, can be used to + generate a VS-mode Software Interrupt. + <%- end -%> + + _Aliases_: + + * `hip.VSSIP` + * `hvip.VSSIP` + * `vsip.SSIP` when `hideleg.VSSI` is set + type: RW + reset_value: 0 + definedBy: H + affectedBy: Smaia + MSIP: + location: 3 + description: | + *Machine Software Interrupt Pending* + + Unused field. + + <%- if ext?(:Smaia) -%> + With AIA/IMSIC, IPIs are delievered as external interrupts. As a result, this bit is + unused and hardwired to 0. + <%- end -%> + type: RO + reset_value: 0 + STIP: + location: 5 + alias: + - sip.STIP + - mvip.STIP + description: | + *Supervisor Timer Interrupt Pending* + + Reports the current pending state of an (H)S-mode timer interrupt + <%- if ext?(:Sstc) -%> + , which is normally controlled by the `stimecmp` CSR. + <%- else -%> + , which is generated by software by writing to `mip.STIP`<% if ext?(:Smaia) %>or its alias `mvip.STIP`<% end %>. + <%- end -%> + + <%-if ext?(:Sstc) -%> + When `menvcfg.STCE` is set, `mip.STIP` is RO-H, and is completely controlled by the timer interrupt device (using `stimecmp`). + + When `menvcfg.STCE` is clear, `mip.STIP` is RW, and M-mode software may write the bit to inject a Supervisor Timer Interrupt. + <%- end -%> + + <% if ext?(:Smaia) %>_Aliases_<% else %>_Alias_<% end %>: + + * `sip.STIP` when `mideleg.STI` is set (though `sip.STIP` is a read-only view) + <%- if ext?(:Smaia) -%> + * `mvip.STIP` when when `menvcfg.STCE` is clear + <%- end -%> + + type: RW + reset_value: 0 + definedBy: S + affectedBy: Sstc + VSTIP: + location: 6 + alias: + - hip.VSTIP + description: | + *Virtual Supervisor Timer Interrupt Pending* + + Reports the current pending state of a VS-mode timer interrupt + <%- if ext?(:Sstc) -%> + , which is normally controlled by the `vstimecmp` CSR, but can also be injected by the hypervisor through `hvip.VSTIP`. + <%- else -%> + , which is generated by M-mode and/or HS-mode software by writing to `hvip.VSTIP`. + <%- end -%> + + <%-if ext?(:Sstc) -%> + When `menvcfg.STCE` is set (enabling the `Sstc` extension), `mip.VSTIP` is the logical OR of `hvip.VSTIP` and the VS-level interrupt signal generated by the timer device (controlled by the value of `vstimecmp`). + + When `menvcfg.STCE` is clear (disabling the `Sstc` extension), `mip.VSTIP` is exactly the value of `hvip.VSTIP`. + <%- end -%> + + `mip.VSTIP` is never writable. If VS-mode software wants to clear the bit, it must do so + <%- if ext?(:Sstc) -%> + by writing the `vstimecmp` register or + <%- end -%> + by calling into the hypervisor (which can then clear `hvip.VSTIP`). + + _Aliases_: + + * `hip.VSTIP` + * `vsip.STIP` when `hideleg.VSTI` is set + * `hvip.VSTIP` <% if ext?(:Sstc) %>when `menvcfg.STCE` is clear<% end %> (though `hvip.VSTIP` is writeable) + type: RO-H + reset_value: 0 + definedBy: H + affectedBy: Sstc + MTIP: + location: 7 + description: | + *Machine Timer Interrupt Pending* + + Reports the current pending state of an M-mode timer interrupt. + + Bit is controlled by the timer device (using `mtimecmp`), and is not writeable. + type: RO-H + reset_value: 0 + SEIP: + location: 9 + alias: + - sip.SEIP + description: | + *Supervisor External Interrupt Pending* + + Reports the current pending state of an (H)S-mode external interrupt. + + This field has two parts: a software-writeable shadow value and a wire from the interrupt controller. + The value presented to software in the bit on a CSR read is the logical OR of the software-writeable value and the interrupt controller value. + When software writes this bit, only the shadow value is updated (the interrupt controller is not notified of the write). + + <%- if ext?(:Smaia) -%> + The software-writeable shadow value is aliased in `mvip.SEIP` (`Smaia` extension). + <%- end -%> + + _Alias_: + + * `sip.SEIP` when `mideleg.SEI` is set (though `sip.SEIP` is read-only) + type: RW-H + definedBy: S + affectedBy: Smaia + reset_value: 0 + VSEIP: + location: 10 + alias: + - hip.VSEIP + - vsip.SEIP + - sip.SEIP + description: | + *Virtual Supervisor External Interrupt Pending* + + Reports the current pending state of a VS-mode external interrupt. + + This field is the logical OR of `hvip.VSEIP` and the wire coming from the interrupt controller. + + The field is not writable by software + <%- if ext?(:Smaia) -%> + (_i.e._, unlike the behavior of `mip.SEIP`/`mvip.SEIP`, attempted writes to `mip.VSEIP` do not propagate to `hvip.VSEIP`) + <%- end -%> + . + + _Aliases_: + + * `hip.VSEIP` + * `vsip.SEIP` when `hideleg.VSEI` is set + type: RO-H + reset_value: 0 + definedBy: H + affectedBy: Smaia + MEIP: + location: 11 + description: | + *Machine External Interrupt Pending* + + Reports the current pending state of an M-mode external interrupt. + + MEIP is controlled by the external interrupt controller <% if ext?(:Smaia) %>(AIA) <% end %>. + It is not writable by software. + type: RO-H + reset_value: 0 + SGEIP: + location: 12 + alias: hip.SGEIP + description: | + *Supervisor Guest External Interrupt Pending* + + Read-only summary of any pending Supervisor Guest External Interrupt Pending, i.e.: + the logical-OR reduction of the `hgeip` register. + + _Alias_: + + * `hip.SGEIP` + type: RO-H + reset_value: 0 + definedBy: H + LCOFIP: + location: 13 + alias: + - sip.LCOFIP + - vsip.LCOFIP + description: | + *Local Counter Overflow Interrupt pending* + + <%- if ext?(:H) -%> + When `hideleg.LCOFI` is set, + `vsip.LCOFIP`, `sip.LCOFIP`, and `mip.LCOFIP` are all aliases. + <%- end -%> + + When a counter overflow interrupt occurs, a hidden sticky bit is set. + + Software writes 0 to `mip.LCOFIP` to clear the pending interrupt. + + <% if ext?(:H) %>_Aliases_<% else %>_Alias_<% end %>: + + * `sip.LCOFIP` when `mideleg.LCOFI` is set + <%- if ext?(:H) -%> + * `vsip.LCOFIP` when `hideleg.LCOFI` is set + <%- end -%> + type: RW-H + reset_value: 0 + definedBy: Sscofpmf \ No newline at end of file diff --git a/arch/csr/misa.yaml b/arch/csr/misa.yaml index c7bf07fb7..7b9f06b70 100644 --- a/arch/csr/misa.yaml +++ b/arch/csr/misa.yaml @@ -1,185 +1,187 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -misa: - long_name: Machine ISA Control - address: 0x301 - priv_mode: M - length: MXLEN - description: Reports the XLEN and "major" extensions supported by the ISA. - definedBy: Sm - fields: - MXL: - location_rv32: 31-30 - location_rv64: 63-62 - description: XLEN in M-mode. - type: RO - reset_value: 2 - A: - location: 0 - description: | - Indicates support for the `A` (atomic) extension. +$schema: "csr_schema.json#" +kind: csr +name: misa +long_name: Machine ISA Control +address: 0x301 +priv_mode: M +length: MXLEN +description: Reports the XLEN and "major" extensions supported by the ISA. +definedBy: Sm +fields: + MXL: + location_rv32: 31-30 + location_rv64: 63-62 + description: XLEN in M-mode. + type: RO + reset_value: 2 + A: + location: 0 + description: | + Indicates support for the `A` (atomic) extension. - [when,"MUTABLE_MISA_A == true"] - Writing 0 to this field will cause all atomic instructions to raise an `IllegalInstruction` exception. - type(): | - return (implemented?(ExtensionName::A) && MUTABLE_MISA_A) ? CsrFieldType::RW : CsrFieldType::RO; - definedBy: A - reset_value: 1 - B: - location: 1 - description: | - Indicates support for the `B` (bitmanip) extension. + [when,"MUTABLE_MISA_A == true"] + Writing 0 to this field will cause all atomic instructions to raise an `IllegalInstruction` exception. + type(): | + return (implemented?(ExtensionName::A) && MUTABLE_MISA_A) ? CsrFieldType::RW : CsrFieldType::RO; + definedBy: A + reset_value: 1 + B: + location: 1 + description: | + Indicates support for the `B` (bitmanip) extension. - [when,"MUTABLE_MISA_B == true"] - Writing 0 to this field will cause all bitmanip instructions to raise an `IllegalInstruction` exception. - type(): | - return (implemented?(ExtensionName::B) && MUTABLE_MISA_B) ? CsrFieldType::RW : CsrFieldType::RO; - definedBy: B - reset_value: 1 - C: - location: 2 - description: | - Indicates support for the `C` (compressed) extension. + [when,"MUTABLE_MISA_B == true"] + Writing 0 to this field will cause all bitmanip instructions to raise an `IllegalInstruction` exception. + type(): | + return (implemented?(ExtensionName::B) && MUTABLE_MISA_B) ? CsrFieldType::RW : CsrFieldType::RO; + definedBy: B + reset_value: 1 + C: + location: 2 + description: | + Indicates support for the `C` (compressed) extension. - [when,"MUTABLE_MISA_C == true"] - Writing 0 to this field will cause all compressed instructions to raise an `IllegalInstruction` exception. - Additionally, IALIGN becomes 32. - type(): | - return (implemented?(ExtensionName::C) && MUTABLE_MISA_C) ? CsrFieldType::RW : CsrFieldType::RO; - definedBy: C - reset_value: 1 - D: - location: 3 - description: | - Indicates support for the `D` (double precision float) extension. + [when,"MUTABLE_MISA_C == true"] + Writing 0 to this field will cause all compressed instructions to raise an `IllegalInstruction` exception. + Additionally, IALIGN becomes 32. + type(): | + return (implemented?(ExtensionName::C) && MUTABLE_MISA_C) ? CsrFieldType::RW : CsrFieldType::RO; + definedBy: C + reset_value: 1 + D: + location: 3 + description: | + Indicates support for the `D` (double precision float) extension. - [when,"MUTABLE_MISA_D == true"] - -- - Writing 0 to this field will cause all double-precision floating point instructions to raise an `IllegalInstruction` exception. + [when,"MUTABLE_MISA_D == true"] + -- + Writing 0 to this field will cause all double-precision floating point instructions to raise an `IllegalInstruction` exception. - Additionally, the upper 32-bits of the f registers will read as zero. - -- - type(): | - return (implemented?(ExtensionName::D) && MUTABLE_MISA_D) ? CsrFieldType::RW : CsrFieldType::RO; - definedBy: D - reset_value: 1 - F: - location: 5 - description: | - Indicates support for the `F` (single precision float) extension. + Additionally, the upper 32-bits of the f registers will read as zero. + -- + type(): | + return (implemented?(ExtensionName::D) && MUTABLE_MISA_D) ? CsrFieldType::RW : CsrFieldType::RO; + definedBy: D + reset_value: 1 + F: + location: 5 + description: | + Indicates support for the `F` (single precision float) extension. - [when,"MUTABLE_MISA_F == true"] - -- - Writing 0 to this field will cause all floating point (single and double precision) instructions to raise an `IllegalInstruction` exception. + [when,"MUTABLE_MISA_F == true"] + -- + Writing 0 to this field will cause all floating point (single and double precision) instructions to raise an `IllegalInstruction` exception. - Writing 0 to this field with `misa.D` set will result in UNDEFINED behavior. - -- - type(): | - return (implemented?(ExtensionName::F) && MUTABLE_MISA_F) ? CsrFieldType::RW : CsrFieldType::RO; - definedBy: F - reset_value: 1 - sw_write(csr_value): | - if (csr_value.F == 0 && csr_value.D == 1) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + Writing 0 to this field with `misa.D` set will result in UNDEFINED behavior. + -- + type(): | + return (implemented?(ExtensionName::F) && MUTABLE_MISA_F) ? CsrFieldType::RW : CsrFieldType::RO; + definedBy: F + reset_value: 1 + sw_write(csr_value): | + if (csr_value.F == 0 && csr_value.D == 1) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } - # fall-through; write the intended value - return csr_value.F; - legal?(csr_value): | - return !(csr_value.F == 0 && csr_value.D == 1); - G: - location: 6 - description: | - Indicates support for all of the following extensions: `I`, `A`, `M`, `F`, `D`. - type(): | - if ((implemented?(ExtensionName::A) && MUTABLE_MISA_A) || - (implemented?(ExtensionName::M) && MUTABLE_MISA_M) || - (implemented?(ExtensionName::F) && MUTABLE_MISA_F) || - (implemented?(ExtensionName::D) && MUTABLE_MISA_D)) { - return CsrFieldType::ROH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - return ( - implemented?(ExtensionName::A) && - implemented?(ExtensionName::M) && - implemented?(ExtensionName::F) && - implemented?(ExtensionName::D)) ? 1 : 0; - H: - location: 7 - description: | - Indicates support for the `H` (hypervisor) extension. + # fall-through; write the intended value + return csr_value.F; + legal?(csr_value): | + return !(csr_value.F == 0 && csr_value.D == 1); + G: + location: 6 + description: | + Indicates support for all of the following extensions: `I`, `A`, `M`, `F`, `D`. + type(): | + if ((implemented?(ExtensionName::A) && MUTABLE_MISA_A) || + (implemented?(ExtensionName::M) && MUTABLE_MISA_M) || + (implemented?(ExtensionName::F) && MUTABLE_MISA_F) || + (implemented?(ExtensionName::D) && MUTABLE_MISA_D)) { + return CsrFieldType::ROH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + return ( + implemented?(ExtensionName::A) && + implemented?(ExtensionName::M) && + implemented?(ExtensionName::F) && + implemented?(ExtensionName::D)) ? 1 : 0; + H: + location: 7 + description: | + Indicates support for the `H` (hypervisor) extension. - [when,"MUTABLE_MISA_H == true"] - Writing 0 to this field will cause all attempts to enter VS- or VU- mode, execute a hypervisor instruction, or access a hypervisor CSR to raise an `IllegalInstruction` fault. - type(): | - return (implemented?(ExtensionName::H) && MUTABLE_MISA_H) ? CsrFieldType::RW : CsrFieldType::RO; - definedBy: H - reset_value: 1 - I: - location: 8 - description: | - Indicates support for the `I` (base) extension. - type: RO - definedBy: I - reset_value: 1 - M: - location: 13 - description: | - Indicates support for the `M` (integer multiply/divide) extension. + [when,"MUTABLE_MISA_H == true"] + Writing 0 to this field will cause all attempts to enter VS- or VU- mode, execute a hypervisor instruction, or access a hypervisor CSR to raise an `IllegalInstruction` fault. + type(): | + return (implemented?(ExtensionName::H) && MUTABLE_MISA_H) ? CsrFieldType::RW : CsrFieldType::RO; + definedBy: H + reset_value: 1 + I: + location: 8 + description: | + Indicates support for the `I` (base) extension. + type: RO + definedBy: I + reset_value: 1 + M: + location: 13 + description: | + Indicates support for the `M` (integer multiply/divide) extension. - [when,"MUTABLE_MISA_M == true"] - Writing 0 to this field will cause all attempts to execute an integer multiply or divide instruction to raise an `IllegalInstruction` exception. - type(): | - return (implemented?(ExtensionName::M) && MUTABLE_MISA_M) ? CsrFieldType::RW : CsrFieldType::RO; - definedBy: M - reset_value: 1 - S: - location: 19 - description: | - Indicates support for the `S` (supervisor mode) extension. + [when,"MUTABLE_MISA_M == true"] + Writing 0 to this field will cause all attempts to execute an integer multiply or divide instruction to raise an `IllegalInstruction` exception. + type(): | + return (implemented?(ExtensionName::M) && MUTABLE_MISA_M) ? CsrFieldType::RW : CsrFieldType::RO; + definedBy: M + reset_value: 1 + S: + location: 19 + description: | + Indicates support for the `S` (supervisor mode) extension. - [when,"MUTABLE_MISA_S == true"] - Writing 0 to this field will cause all attempts to enter S-mode or access S-mode state to raise an exception. - type(): | - return (implemented?(ExtensionName::S) && MUTABLE_MISA_S) ? CsrFieldType::RW : CsrFieldType::RO; - definedBy: S - reset_value: 1 - U: - location: 21 - description: | - Indicates support for the `U` (user mode) extension. + [when,"MUTABLE_MISA_S == true"] + Writing 0 to this field will cause all attempts to enter S-mode or access S-mode state to raise an exception. + type(): | + return (implemented?(ExtensionName::S) && MUTABLE_MISA_S) ? CsrFieldType::RW : CsrFieldType::RO; + definedBy: S + reset_value: 1 + U: + location: 21 + description: | + Indicates support for the `U` (user mode) extension. - [when,"MUTABLE_MISA_U == true"] - Writing 0 to this field will cause all attempts to enter U-mode to raise an exception. - type(): | - return (implemented?(ExtensionName::U) && MUTABLE_MISA_U) ? CsrFieldType::RW : CsrFieldType::RO; - definedBy: U - reset_value: 1 - V: - location: 22 - description: | - Indicates support for the `V` (vector) extension. + [when,"MUTABLE_MISA_U == true"] + Writing 0 to this field will cause all attempts to enter U-mode to raise an exception. + type(): | + return (implemented?(ExtensionName::U) && MUTABLE_MISA_U) ? CsrFieldType::RW : CsrFieldType::RO; + definedBy: U + reset_value: 1 + V: + location: 22 + description: | + Indicates support for the `V` (vector) extension. - [when,"MUTABLE_MISA_V == true"] - Writing 0 to this field will cause all attempts to execute a vector instruction to raise an `IllegalInstruction` trap. - type: RO - definedBy: V - reset_value: 1 - sw_read(): | - return ( - (CSR[misa].MXL << 62) | - (CSR[misa].V << 21) | - (CSR[misa].U << 20) | - (CSR[misa].S << 18) | - (CSR[misa].M << 12) | - (CSR[misa].I << 7) | - (CSR[misa].H << 6) | - ((CSR[misa].A & CSR[misa].M & CSR[misa].F & CSR[misa].D) << 5) | # 'G' - (CSR[misa].F << 4) | - (CSR[misa].D << 3) | - (CSR[misa].C << 2) | - (CSR[misa].B << 1) | - CSR[misa].A); - \ No newline at end of file + [when,"MUTABLE_MISA_V == true"] + Writing 0 to this field will cause all attempts to execute a vector instruction to raise an `IllegalInstruction` trap. + type: RO + definedBy: V + reset_value: 1 +sw_read(): | + return ( + (CSR[misa].MXL << 62) | + (CSR[misa].V << 21) | + (CSR[misa].U << 20) | + (CSR[misa].S << 18) | + (CSR[misa].M << 12) | + (CSR[misa].I << 7) | + (CSR[misa].H << 6) | + ((CSR[misa].A & CSR[misa].M & CSR[misa].F & CSR[misa].D) << 5) | # 'G' + (CSR[misa].F << 4) | + (CSR[misa].D << 3) | + (CSR[misa].C << 2) | + (CSR[misa].B << 1) | + CSR[misa].A); + \ No newline at end of file diff --git a/arch/csr/mscratch.yaml b/arch/csr/mscratch.yaml index 93950d751..9a95af596 100644 --- a/arch/csr/mscratch.yaml +++ b/arch/csr/mscratch.yaml @@ -1,16 +1,18 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mscratch: - long_name: Machine Scratch Register - address: 0x340 - priv_mode: M - length: MXLEN - description: Scratch register for software use. Bits are not interpreted by hardware. - definedBy: Sm - fields: - SCRATCH: - location_rv32: 31-0 - location_rv64: 63-0 - description: Scratch value - type: RW - reset_value: 0 \ No newline at end of file +$schema: "csr_schema.json#" +kind: csr +name: mscratch +long_name: Machine Scratch Register +address: 0x340 +priv_mode: M +length: MXLEN +description: Scratch register for software use. Bits are not interpreted by hardware. +definedBy: Sm +fields: + SCRATCH: + location_rv32: 31-0 + location_rv64: 63-0 + description: Scratch value + type: RW + reset_value: 0 \ No newline at end of file diff --git a/arch/csr/mseccfg.yaml b/arch/csr/mseccfg.yaml index 2cbc905e6..bc76cd886 100644 --- a/arch/csr/mseccfg.yaml +++ b/arch/csr/mseccfg.yaml @@ -1,13 +1,14 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mseccfg: - long_name: Machine Security Configuration - address: 0x747 - priv_mode: M - length: 64 - description: Machine Security Configuration - definedBy: - name: Sm - version: ">= 1.12" - fields: {} - \ No newline at end of file +$schema: "csr_schema.json#" +kind: csr +name: mseccfg +long_name: Machine Security Configuration +address: 0x747 +priv_mode: M +length: 64 +description: Machine Security Configuration +definedBy: + name: Sm + version: ">= 1.12" +fields: {} diff --git a/arch/csr/mseccfgh.yaml b/arch/csr/mseccfgh.yaml index 80a5a721f..16d719641 100644 --- a/arch/csr/mseccfgh.yaml +++ b/arch/csr/mseccfgh.yaml @@ -1,13 +1,14 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mseccfgh: - long_name: Most significant 32 bits of Machine Security Configuration - address: 0x757 - priv_mode: M - length: 32 - description: Machine Security Configuration - definedBy: - name: Sm - version: ">= 1.12" - fields: {} - \ No newline at end of file +$schema: "csr_schema.json#" +kind: csr +name: mseccfgh +long_name: Most significant 32 bits of Machine Security Configuration +address: 0x757 +priv_mode: M +length: 32 +description: Machine Security Configuration +definedBy: + name: Sm + version: ">= 1.12" +fields: {} diff --git a/arch/csr/mstatus.yaml b/arch/csr/mstatus.yaml index 013036325..9461de08a 100644 --- a/arch/csr/mstatus.yaml +++ b/arch/csr/mstatus.yaml @@ -1,592 +1,593 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mstatus: - long_name: Machine Status - address: 0x300 - priv_mode: M - - # length is MXLEN-bit - # - # MXLEN cannot change dynamically, so this will be converted to an integer - # in the genrated, configuration-dependent spec - length: MXLEN - - description: The mstatus register tracks and controls the hart's current operating state. - definedBy: Sm - fields: - SD: - location_rv32: 31 - location_rv64: 63 - description: | - State Dirty. - - Read-only bit that summarizes whether either the FS, XS, or VS - fields signal the presence of some dirty state. - definedBy: - anyOf: [F,V] # NOTE: if you implement a custom extension overlay that writes to XS, then you need to add your extension here in the overlay as well - type(): | - # this is read-only if FS and VS are both read-only - # otherwise, it is read-only with hardware update - - if (implemented?(ExtensionName::F) && (HW_MSTATUS_FS_DIRTY_UPDATE != "never")) { - return CsrFieldType::ROH; - } else if (implemented?(ExtensionName::V) && (HW_MSTATUS_VS_DIRTY_UPDATE != "never")) { - return CsrFieldType::ROH; - } else { - return CsrFieldType::RO; - } - reset_value(): | - # the reset value is known if both FS and VS are legal - # make this a function call so that it can be displayed succinctly in docs - - if (mstatus_sd_has_known_reset()) { - return mstatus_sd_reset_value(); - } else { - return UNDEFINED_LEGAL; - } - - MPV: - location: 39 - base: 64 - description: | - *Machine Previous Virtualization mode* - - Written with the prior virtualization mode when entering M-mode from an exception/interrupt. - When returning via an MRET instruction, the virtualization mode becomes the value of MPV unless MPP=3, in which case the virtualization mode is always 0. - Can also be written by software. - type: RW-H - reset_value: UNDEFINED_LEGAL - definedBy: H - GVA: - location: 38 - base: 64 - description: | - *Guest Virtual Address* - - When a trap is taken and a guest virtual address is written into mtval, GVA is set. - When a trap is taken and a guest virtual address is written into mtval, GVA is cleared. - type: RW-H - reset_value: 0 - definedBy: H - MBE: - location: 37 - base: 64 - description: | - *M-mode Big Endian* - - Controls the endianness of data M-mode (0 = little, 1 = big). - Instructions are always little endian, regardless of the data setting. - - [when,"M_MODE_ENDIANESS == little"] - Since the CPU does not support big endian, this is hardwired to 0. - - [when,"M_MODE_ENDIANESS == big"] - Since the CPU does not support little endian, this is hardwired to 1. - type(): | - return (M_MODE_ENDIANESS == "dynamic") ? CsrFieldType::RW : CsrFieldType::RO; - - # if endianness is mutable, MBE comes out of reset in little-endian mode - reset_value(): | - return (M_MODE_ENDIANESS == "big") ? 1 : 0; - - SBE: - location: 36 - base: 64 - definedBy: S - description: | - *S-mode Big Endian* - - Controls the endianness of S-mode (0 = little, 1 = big). - Instructions are always little endian, regardless of the data setting. - - [when,"S_MODE_ENDIANESS == little"] - Since the CPU does not support big endian, this is hardwired to 0. - - [when,"S_MODE_ENDIANESS == big"] - Since the CPU does not support litte endian, this is hardwired to 1. - type(): | - return (S_MODE_ENDIANESS == "dynamic") ? CsrFieldType::RW : CsrFieldType::RO; - - # if endianess is mutable, MBE comes out of reset in little-endian mode - reset_value(): | - if (S_MODE_ENDIANESS == "little") { - return 0; - } else if (S_MODE_ENDIANESS == "big") { - return 1; - } else { - return UNDEFINED_LEGAL; - } - SXL: - location: 35-34 - base: 64 - definedBy: S - description: | - *S-mode XLEN* - - Sets the effective XLEN for S-mode (0 = 32-bit, 1 = 64-bit, 2 = 128-bit [reserved]). - - [when,"SXLEN==32"] - Since the CPU only supports SXLEN==32, this is hardwired to 0. - - [when,"SXLEN==32"] - Since the CPU only supports SXLEN==64, this is hardwired to 1. - - [when,"SXLEN=3264"] - -- - It is not valid to have SXLEN less than UXLEN. - - It is UNDEFINED_LEGAL what will happen if a software sets `mstatus.SXL` to be greater than `mstatus.UXL`. - - It is UNDEFINED_LEGAL to set the MSB of SXL. - -- - type(): | - return (implemented?(ExtensionName::S) && SXLEN == 3264) ? CsrFieldType::RW : CsrFieldType::RO; - - legal?(csr_value): | - if (SXLEN == 32) { - # SXLEN == 32 is encoded as 0 - return csr_value.SXL == 0; - } else if (SXLEN == 64) { - # SXLEN == 64 is encoded as 1 - return csr_value.SXL == 1; - } else { - # SXLEN could be 32 or 64 - return csr_value.SXL <= 1; - } - - sw_write(csr_value): | - if (csr_value.SXL < csr_value.UXL) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (csr_value.SXL > 1) { - # SXL != [0, 1] is not defined (2 reserved for RV128, but that isn't ratified) - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.SXL; - } - reset_value: UNDEFINED_LEGAL - - UXL: - location: 33-32 - base: 64 - definedBy: U - description: | - U-mode XLEN. - - Sets the effective XLEN for U-mode (0 = 32-bit, 1 = 64-bit, 2 = 128-bit [reserved]). - - [when,"UXLEN == 32"] - Since the CPU only supports UXLEN==32, this is hardwired to 0. - - [when,"UXLEN == 64"] - Since the CPU only supports UXLEN==64, this is hardwired to 1. - - - [when,"UXLEN == 3264"] - -- - It is not valid to have SXLEN less than UXLEN. - - It is UNDEFINED_LEGAL what will happen if a software sets `mstatus.SXL` to be greater than `mstatus.UXL`. - - It is UNDEFINED_LEGAL to set the MSB of UXL. - -- - type(): | - return (UXLEN == 3264) ? CsrFieldType::RW : CsrFieldType::RO; - - sw_write(csr_value): | - if (csr_value.SXL < csr_value.UXL) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (csr_value.UXL > 1) { - # UXL != [0, 1] is not defined (2 reserved for RV128, but that isn't ratified) - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.UXL; - } - - legal?(csr_value): | - if (UXLEN == 32) { - return csr_value.UXL == 0; - } else if (UXLEN == 64) { - return csr_value.UXL == 1; - } else { - return csr_value.UXL <= 1; - } - - reset_value(): | - if (UXLEN == 32) { - return 0; - } else if (UXLEN == 64) { - return 1; - } else { - return UNDEFINED_LEGAL; - } - - TSR: - location: 22 - description: | - *Trap SRET* - - When 1, attempts to execute the `sret` instruction while executing in HS/S-mode - will raise an Illegal Instruction exception. - - [when,"ext?(:H)"] - Does not affect the behavior of `sret` in VS_mode (see `hstatus.VTSR`). - type: RW - definedBy: S - reset_value: UNDEFINED_LEGAL - TW: - location: 21 - description: | - *Timeout Wait* - - When 1, the WFI instruction will raise an Illegal Instruction trap after an - implementaion-defined wait period when executed in a mode other than M-mode. - - When 0, the `wfi` instruction is permitted to wait forever in (H)S-mode but must - trap after an implementation-defined wait period in U-mode. - type: RW - definedBy: S - reset_value: UNDEFINED_LEGAL - TVM: - location: 20 - description: | - Trap Virtual Memory. - - When 1, an `Illegal Instruction` trap occurs when - - * writing the `satp` CSR, executing an `sfence.vma`, or executing an `sinval.vma` while in (H)S-mode (but not VS-mode) - * writing the `hgtap` CSR, executing an `hfence.gvma`, or executing an `hinval.gvma` while in HS-mode - - Notably, `mstatus.TVM` does *not* cause - - *`hfence.vvma`, `sfence.w.inval`, or `sfence.inval.ir` to trap. - * Any additional traps in VS-mode (controlled via `hstatus.VTVM` instead). - - type(): | - if (CSR[misa].S == 1'b0) { - return CsrFieldType::RO; - } else { - return CsrFieldType::RW; - } - definedBy: S - reset_value(): | - if (CSR[misa].S == 1'b0) { - return 0; - } else if (MSTATUS_TVM_IMPLEMENTED) { - return UNDEFINED_LEGAL; - } else { - return 0; - } - sw_write(csr_value): | - if (CSR[misa].S == 1'b0) { - return 0; - } else if (MSTATUS_TVM_IMPLEMENTED) { - return csr_value.TVM; - } else { - return 0; - } - MXR: - location: 19 - description: | - Make eXecutable Readable. - - When 1, loads from pages marked readable *or executable* are allowed. - When 0, loads from pages marked executable raise a Page Fault exception. - definedBy: S - type: RW - reset_value: UNDEFINED_LEGAL - SUM: - location: 18 - description: | - permit Supervisor Memory Access. - - When 0, an S-mode read or an M-mode read with mstatus.MPRV=1 and mstatus.MPP=01 - to a 'U' (user) page will cause an ILLEGAL INSTRUCTION exception. - definedBy: S - type(): | - # only writable if there is some translation supported - if (has_virt_mem?()) { - return CsrFieldType::RW; - } else { - return CsrFieldType::RO; - } - reset_value(): | - if (has_virt_mem?()) { - return UNDEFINED_LEGAL; - } else { - # read-only zero when there is no virtual memory - return 0; - } - MPRV: - location: 17 - description: | - Modify PRiVilege. - - When 1, loads and stores behave as if the current virutalization mode:privilege level was - `mstatus.MPV`:`mstatus.MPP`. - - `mstatus.MPRV` is cleared on any exception return (`mret` or `sret` instruction, regardless of the trap handler privilege mode). - definedBy: U - type(): | - return (CSR[misa].U == 1'b1) ? CsrFieldType::RWH : CsrFieldType::RO; - reset_value: 0 - XS: - location: 16-15 - description: | - *Custom (X) extension context Status* - - Summarizes the current state of any custom extension state. - Either 0 - Off, 1 - Initial, 2 - Clean, 3 - Dirty. - Since there are no custom extensions in the base spec, this field is read-only 0. - type: RO - reset_value: 0 - FS: - location: 14-13 - description: | - Floating point context status. - - When 0, floating point instructions (from F and D extensions) are disabled, - and cause `ILLEGAL INSTRUCTION` exceptions. - When a floating point register, or the fCSR register is written, FS obtains the value 3. - Values 1 and 2 are valid write values for software, but are not interpreted by hardware - other than to possibly enable a previously-disabled floating point unit. - type(): | - if (CSR[misa].F == 1'b1){ - return CsrFieldType::RWH; - } else if ((CSR[misa].S == 1'b0) && (CSR[misa].F == 1'b0)) { - # must be read-only-0 - return CsrFieldType::RO; - } else { - # there will be no hardware update in this case because we know the F extension isn't implemented - return MSTATUS_FS_WRITEABLE ? CsrFieldType::RW : CsrFieldType::RO; - } - definedBy: - anyOf: [F, S] - reset_value(): | - if (CSR[misa].F == 1'b1){ - return UNDEFINED_LEGAL; - } else if ((CSR[misa].S == 1'b0) && (CSR[misa].F == 1'b0)) { - # must be read-only-0 - return 0; - } else { - # there will be no hardware update in this case because we know the F extension isn't implemented - return MSTATUS_FS_WRITEABLE ? UNDEFINED_LEGAL : 0; - } - sw_write(csr_value): | - if (CSR[misa].F == 1'b1){ - return ary_includes?<$array_size(MSTATUS_FS_LEGAL_VALUES), 2>(MSTATUS_FS_LEGAL_VALUES, csr_value.FS) ? csr_value.FS : UNDEFINED_LEGAL_DETERMINISTIC; - } else if ((CSR[misa].S == 1'b0) && (CSR[misa].F == 1'b0)) { - # must be read-only-0 - return 0; - } else { - # there will be no hardware update in this case because we know the F extension isn't implemented - return ary_includes?<$array_size(MSTATUS_FS_LEGAL_VALUES), 2>(MSTATUS_FS_LEGAL_VALUES, csr_value.FS) ? csr_value.FS : UNDEFINED_LEGAL_DETERMINISTIC; - } - MPP: - location: 12-11 - description: | - M-mode Previous Privilege. - - Written by hardware in two cases: - - * Written with the prior nominal privilege level when entering M-mode from an exception/interrupt. - * Written with 0 when executing an `mret` instruction to return from an exception in M-mode. - - Can also be written by software without immediate side-effect. - - Affects execution in two cases: - - * On a return from an exception from M-mode, the machine will - enter the privilege level stored in MPP before clearing the field. - * When `mstatus.MPRV` is set, loads and stores behave as if the current privlege level were MPP. - type: RW-H - reset_value: UNDEFINED_LEGAL - sw_write(csr_value): | - if (csr_value.MPP == 2'b01 && !implemented?(ExtensionName::S)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (csr_value.MPP == 2'b00 && !implemented?(ExtensionName::U)) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else if (csr_value.MPP == 2'b10) { - # never a valid value - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.MPP; - } - legal?(csr_value): | - if (csr_value.MPP == 2'b01 && !implemented?(ExtensionName::S)) { - return false; - } else if (csr_value.MPP == 2'b00 && !implemented?(ExtensionName::U)) { - return false; - } else if (csr_value.MPP == 2'b10) { - # never a valid value - return flase; - } else { - return true; - } - VS: - location: 10-9 - description: | - Vector context status. - - When 0, vector instructions (from the V extension) are disabled, and cause ILLEGAL INSTRUCTION exceptions. - When a vector register or vector CSR is written, VS obtains the value 3. - Values 1 and 2 are valid write values for software, but are not interpreted by hardware - other than to possibly enable a previously-disabled vector unit. - definedBy: - anyOf: [V, S] - type(): | - if (CSR[misa].V == 1'b1){ - return CsrFieldType::RWH; - } else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) { - # must be read-only-0 - return CsrFieldType::RO; - } else { - # there will be no hardware update in this case because we know the V extension isn't implemented - return MSTATUS_VS_WRITEABLE ? CsrFieldType::RW : CsrFieldType::RO; - } - reset_value(): | - if (CSR[misa].V == 1'b1){ - return UNDEFINED_LEGAL; - } else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) { - # must be read-only-0 - return 0; - } else { - # there will be no hardware update in this case because we know the V extension isn't implemented - return MSTATUS_VS_WRITEABLE ? UNDEFINED_LEGAL : 0; - } - sw_write(csr_value): | - if (CSR[misa].V == 1'b1){ - return ary_includes?<$array_size(MSTATUS_VS_LEGAL_VALUES), 2>(MSTATUS_VS_LEGAL_VALUES, csr_value.FS) ? csr_value.FS : UNDEFINED_LEGAL_DETERMINISTIC; - } else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) { - # must be read-only-0 - return 0; - } else { - # there will be no hardware update in this case because we know the V extension isn't implemented - return ary_includes?<$array_size(MSTATUS_VS_LEGAL_VALUES), 2>(MSTATUS_VS_LEGAL_VALUES, csr_value.FS) ? csr_value.FS : UNDEFINED_LEGAL_DETERMINISTIC; - } - SPP: - location: 8 - description: | - *S-mode Previous Privilege* - - Written by hardware in two cases: - - * Written with the prior nominal privilege level when entering (H)S-mode from an exception/interrupt. - * Written with 0 when executing an `sret` instruction to return from an exception in (H)S-mode or (unlikely) M-mode. - - Can also be written by software without immediate side-effect. - - Affects execution in one case: - - * On a return from an exception using the `sret` instruction in (H)S-mode or (unlikely) M-mode, - the machine will enter the privilege level stored in SPP before clearing the field. - - Notably, `mstatus.SPP` does not affect exception return in VS-mode (see `vsstatus.SPP`). - - type: RW-H - definedBy: S - reset_value: UNDEFINED_LEGAL - sw_write(csr_value): | - if (csr_value.SPP == 2'b10) { - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - return csr_value.SPP; - } - legal?(csr_value): | - return csr_value.SPP != 2'b10; - MPIE: - location: 7 - description: | - *M-mode Previous Interrupt Enable* - - Written by hardware in two cases: - - * Written with prior value of `mstatus.MIE` when entering M-mode from an exception/interrupt. - * Writen with the value 1 when returning from an exception in M-mode (via the `mret` instruction). - - Can also be written by software without immediate side effect. - - Other than serving as a record of nested traps as described above, `mstatus.MPIE` does not affect execution. - - type: RW-H - reset_value: UNDEFINED_LEGAL - UBE: - location: 6 - definedBy: U - description: | - *U-mode Big Endian* - - Controls the endianness of U-mode (0 = little, 1 = big). - Instructions are always little endian, regardless of the data setting. - - [when,"U_MODE_ENDIANESS == 'little'"] - Since the CPU does not support big endian in U-mode, this is hardwired to 0. - - [when,"U_MODE_ENDIANESS == 'big'"] - Since the CPU does not support litte endian in U-mode, this is hardwired to 1. - type(): | - return (U_MODE_ENDIANESS == "dynamic") ? CsrFieldType::RW : CsrFieldType::RO; - - reset_value(): | - if (U_MODE_ENDIANESS == "little") { - return 0; - } else if (U_MODE_ENDIANESS == "big") { - return 1; - } else { - return UNDEFINED_LEGAL; - } - - SPIE: - location: 5 - description: | - *S-mode Previous Interrupt Enable* - - Written by hardware in two cases: - - * Written with prior value of `mstatus.SIE` when entering (H)S-mode from an exception/interrupt. - * Writen with the value 1 when returning from an exception via the `sret` instruction in (H)S-mode or (unlikely) M-mode. - - Can also be written by software without immediate side effect. - - Other than serving as a record of nested traps as described above, `mstatus.SPIE` does not affect execution. - type(): | - return (CSR[misa].S == 1'b1) ? CsrFieldType::RWH : CsrFieldType::RO; - definedBy: S - reset_value(): | - return (CSR[misa].S == 1'b1) ? UNDEFINED_LEGAL : 0; - MIE: - location: 3 - description: | - *M-mode Interrupt Enable* - - Written by hardware in two cases: - - * Written with the value 0 when entering M-mode from an exception/interrupt. - * Written with the prior value of `mstatus.MPIE` when returning from an exeception in M-mode (via `mret`). - - Affects execution by: - - * When 0, all interrupts are disabled when the current privilege level is M. - * When 1, interrupts that are not otherwise disabled with a field in `mie` are enabled. - - type: RW-H - reset_value: 0 - SIE: - location: 1 - description: | - *S-mode Interrupt Enable* - - Written by hardware in two cases: - - * Written with the value 0 when entering (H)S-mode from an exception/interrupt. - * Written with the prior value of `mstatus.SPIE` when returning from an exeception via `sret` in (H)S-mode or (unlikely) M-mode. - - Affects execution by: - - * When 0, all (H)S-mode interrupts are disabled when the current privilege level is (H)S (M-mode interrupts are still enabled). - * When 1, (H)S-mode interrupts that are not otherwise disabled with a field in `sie` are enabled. - - type(): | - return (CSR[misa].S == 1'b1) ? CsrFieldType::RWH : CsrFieldType::RO; - definedBy: S - reset_value(): | - return (CSR[misa].S == 1'b1) ? UNDEFINED_LEGAL : 0; +$schema: "csr_schema.json#" +kind: csr +name: mstatus +long_name: Machine Status +address: 0x300 +priv_mode: M + +# length is MXLEN-bit +# +# MXLEN cannot change dynamically, so this will be converted to an integer +# in the genrated, configuration-dependent spec +length: MXLEN +description: The mstatus register tracks and controls the hart's current operating state. +definedBy: Sm +fields: + SD: + location_rv32: 31 + location_rv64: 63 + description: | + State Dirty. + + Read-only bit that summarizes whether either the FS, XS, or VS + fields signal the presence of some dirty state. + definedBy: + anyOf: [F,V] # NOTE: if you implement a custom extension overlay that writes to XS, then you need to add your extension here in the overlay as well + type(): | + # this is read-only if FS and VS are both read-only + # otherwise, it is read-only with hardware update + + if (implemented?(ExtensionName::F) && (HW_MSTATUS_FS_DIRTY_UPDATE != "never")) { + return CsrFieldType::ROH; + } else if (implemented?(ExtensionName::V) && (HW_MSTATUS_VS_DIRTY_UPDATE != "never")) { + return CsrFieldType::ROH; + } else { + return CsrFieldType::RO; + } + reset_value(): | + # the reset value is known if both FS and VS are legal + # make this a function call so that it can be displayed succinctly in docs + + if (mstatus_sd_has_known_reset()) { + return mstatus_sd_reset_value(); + } else { + return UNDEFINED_LEGAL; + } + + MPV: + location: 39 + base: 64 + description: | + *Machine Previous Virtualization mode* + + Written with the prior virtualization mode when entering M-mode from an exception/interrupt. + When returning via an MRET instruction, the virtualization mode becomes the value of MPV unless MPP=3, in which case the virtualization mode is always 0. + Can also be written by software. + type: RW-H + reset_value: UNDEFINED_LEGAL + definedBy: H + GVA: + location: 38 + base: 64 + description: | + *Guest Virtual Address* + + When a trap is taken and a guest virtual address is written into mtval, GVA is set. + When a trap is taken and a guest virtual address is written into mtval, GVA is cleared. + type: RW-H + reset_value: 0 + definedBy: H + MBE: + location: 37 + base: 64 + description: | + *M-mode Big Endian* + + Controls the endianness of data M-mode (0 = little, 1 = big). + Instructions are always little endian, regardless of the data setting. + + [when,"M_MODE_ENDIANESS == little"] + Since the CPU does not support big endian, this is hardwired to 0. + + [when,"M_MODE_ENDIANESS == big"] + Since the CPU does not support little endian, this is hardwired to 1. + type(): | + return (M_MODE_ENDIANESS == "dynamic") ? CsrFieldType::RW : CsrFieldType::RO; + + # if endianness is mutable, MBE comes out of reset in little-endian mode + reset_value(): | + return (M_MODE_ENDIANESS == "big") ? 1 : 0; + + SBE: + location: 36 + base: 64 + definedBy: S + description: | + *S-mode Big Endian* + + Controls the endianness of S-mode (0 = little, 1 = big). + Instructions are always little endian, regardless of the data setting. + + [when,"S_MODE_ENDIANESS == little"] + Since the CPU does not support big endian, this is hardwired to 0. + + [when,"S_MODE_ENDIANESS == big"] + Since the CPU does not support litte endian, this is hardwired to 1. + type(): | + return (S_MODE_ENDIANESS == "dynamic") ? CsrFieldType::RW : CsrFieldType::RO; + + # if endianess is mutable, MBE comes out of reset in little-endian mode + reset_value(): | + if (S_MODE_ENDIANESS == "little") { + return 0; + } else if (S_MODE_ENDIANESS == "big") { + return 1; + } else { + return UNDEFINED_LEGAL; + } + SXL: + location: 35-34 + base: 64 + definedBy: S + description: | + *S-mode XLEN* + + Sets the effective XLEN for S-mode (0 = 32-bit, 1 = 64-bit, 2 = 128-bit [reserved]). + + [when,"SXLEN==32"] + Since the CPU only supports SXLEN==32, this is hardwired to 0. + + [when,"SXLEN==32"] + Since the CPU only supports SXLEN==64, this is hardwired to 1. + + [when,"SXLEN=3264"] + -- + It is not valid to have SXLEN less than UXLEN. + + It is UNDEFINED_LEGAL what will happen if a software sets `mstatus.SXL` to be greater than `mstatus.UXL`. + + It is UNDEFINED_LEGAL to set the MSB of SXL. + -- + type(): | + return (implemented?(ExtensionName::S) && SXLEN == 3264) ? CsrFieldType::RW : CsrFieldType::RO; + + legal?(csr_value): | + if (SXLEN == 32) { + # SXLEN == 32 is encoded as 0 + return csr_value.SXL == 0; + } else if (SXLEN == 64) { + # SXLEN == 64 is encoded as 1 + return csr_value.SXL == 1; + } else { + # SXLEN could be 32 or 64 + return csr_value.SXL <= 1; + } + + sw_write(csr_value): | + if (csr_value.SXL < csr_value.UXL) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (csr_value.SXL > 1) { + # SXL != [0, 1] is not defined (2 reserved for RV128, but that isn't ratified) + return UNDEFINED_LEGAL_DETERMINISTIC; + } else { + return csr_value.SXL; + } + reset_value: UNDEFINED_LEGAL + + UXL: + location: 33-32 + base: 64 + definedBy: U + description: | + U-mode XLEN. + + Sets the effective XLEN for U-mode (0 = 32-bit, 1 = 64-bit, 2 = 128-bit [reserved]). + + [when,"UXLEN == 32"] + Since the CPU only supports UXLEN==32, this is hardwired to 0. + + [when,"UXLEN == 64"] + Since the CPU only supports UXLEN==64, this is hardwired to 1. + + + [when,"UXLEN == 3264"] + -- + It is not valid to have SXLEN less than UXLEN. + + It is UNDEFINED_LEGAL what will happen if a software sets `mstatus.SXL` to be greater than `mstatus.UXL`. + + It is UNDEFINED_LEGAL to set the MSB of UXL. + -- + type(): | + return (UXLEN == 3264) ? CsrFieldType::RW : CsrFieldType::RO; + + sw_write(csr_value): | + if (csr_value.SXL < csr_value.UXL) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (csr_value.UXL > 1) { + # UXL != [0, 1] is not defined (2 reserved for RV128, but that isn't ratified) + return UNDEFINED_LEGAL_DETERMINISTIC; + } else { + return csr_value.UXL; + } + + legal?(csr_value): | + if (UXLEN == 32) { + return csr_value.UXL == 0; + } else if (UXLEN == 64) { + return csr_value.UXL == 1; + } else { + return csr_value.UXL <= 1; + } + + reset_value(): | + if (UXLEN == 32) { + return 0; + } else if (UXLEN == 64) { + return 1; + } else { + return UNDEFINED_LEGAL; + } + + TSR: + location: 22 + description: | + *Trap SRET* + + When 1, attempts to execute the `sret` instruction while executing in HS/S-mode + will raise an Illegal Instruction exception. + + [when,"ext?(:H)"] + Does not affect the behavior of `sret` in VS_mode (see `hstatus.VTSR`). + type: RW + definedBy: S + reset_value: UNDEFINED_LEGAL + TW: + location: 21 + description: | + *Timeout Wait* + + When 1, the WFI instruction will raise an Illegal Instruction trap after an + implementaion-defined wait period when executed in a mode other than M-mode. + + When 0, the `wfi` instruction is permitted to wait forever in (H)S-mode but must + trap after an implementation-defined wait period in U-mode. + type: RW + definedBy: S + reset_value: UNDEFINED_LEGAL + TVM: + location: 20 + description: | + Trap Virtual Memory. + + When 1, an `Illegal Instruction` trap occurs when + + * writing the `satp` CSR, executing an `sfence.vma`, or executing an `sinval.vma` while in (H)S-mode (but not VS-mode) + * writing the `hgtap` CSR, executing an `hfence.gvma`, or executing an `hinval.gvma` while in HS-mode + + Notably, `mstatus.TVM` does *not* cause + + *`hfence.vvma`, `sfence.w.inval`, or `sfence.inval.ir` to trap. + * Any additional traps in VS-mode (controlled via `hstatus.VTVM` instead). + + type(): | + if (CSR[misa].S == 1'b0) { + return CsrFieldType::RO; + } else { + return CsrFieldType::RW; + } + definedBy: S + reset_value(): | + if (CSR[misa].S == 1'b0) { + return 0; + } else if (MSTATUS_TVM_IMPLEMENTED) { + return UNDEFINED_LEGAL; + } else { + return 0; + } + sw_write(csr_value): | + if (CSR[misa].S == 1'b0) { + return 0; + } else if (MSTATUS_TVM_IMPLEMENTED) { + return csr_value.TVM; + } else { + return 0; + } + MXR: + location: 19 + description: | + Make eXecutable Readable. + + When 1, loads from pages marked readable *or executable* are allowed. + When 0, loads from pages marked executable raise a Page Fault exception. + definedBy: S + type: RW + reset_value: UNDEFINED_LEGAL + SUM: + location: 18 + description: | + permit Supervisor Memory Access. + + When 0, an S-mode read or an M-mode read with mstatus.MPRV=1 and mstatus.MPP=01 + to a 'U' (user) page will cause an ILLEGAL INSTRUCTION exception. + definedBy: S + type(): | + # only writable if there is some translation supported + if (has_virt_mem?()) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } + reset_value(): | + if (has_virt_mem?()) { + return UNDEFINED_LEGAL; + } else { + # read-only zero when there is no virtual memory + return 0; + } + MPRV: + location: 17 + description: | + Modify PRiVilege. + + When 1, loads and stores behave as if the current virutalization mode:privilege level was + `mstatus.MPV`:`mstatus.MPP`. + + `mstatus.MPRV` is cleared on any exception return (`mret` or `sret` instruction, regardless of the trap handler privilege mode). + definedBy: U + type(): | + return (CSR[misa].U == 1'b1) ? CsrFieldType::RWH : CsrFieldType::RO; + reset_value: 0 + XS: + location: 16-15 + description: | + *Custom (X) extension context Status* + + Summarizes the current state of any custom extension state. + Either 0 - Off, 1 - Initial, 2 - Clean, 3 - Dirty. + Since there are no custom extensions in the base spec, this field is read-only 0. + type: RO + reset_value: 0 + FS: + location: 14-13 + description: | + Floating point context status. + + When 0, floating point instructions (from F and D extensions) are disabled, + and cause `ILLEGAL INSTRUCTION` exceptions. + When a floating point register, or the fCSR register is written, FS obtains the value 3. + Values 1 and 2 are valid write values for software, but are not interpreted by hardware + other than to possibly enable a previously-disabled floating point unit. + type(): | + if (CSR[misa].F == 1'b1){ + return CsrFieldType::RWH; + } else if ((CSR[misa].S == 1'b0) && (CSR[misa].F == 1'b0)) { + # must be read-only-0 + return CsrFieldType::RO; + } else { + # there will be no hardware update in this case because we know the F extension isn't implemented + return MSTATUS_FS_WRITEABLE ? CsrFieldType::RW : CsrFieldType::RO; + } + definedBy: + anyOf: [F, S] + reset_value(): | + if (CSR[misa].F == 1'b1){ + return UNDEFINED_LEGAL; + } else if ((CSR[misa].S == 1'b0) && (CSR[misa].F == 1'b0)) { + # must be read-only-0 + return 0; + } else { + # there will be no hardware update in this case because we know the F extension isn't implemented + return MSTATUS_FS_WRITEABLE ? UNDEFINED_LEGAL : 0; + } + sw_write(csr_value): | + if (CSR[misa].F == 1'b1){ + return ary_includes?<$array_size(MSTATUS_FS_LEGAL_VALUES), 2>(MSTATUS_FS_LEGAL_VALUES, csr_value.FS) ? csr_value.FS : UNDEFINED_LEGAL_DETERMINISTIC; + } else if ((CSR[misa].S == 1'b0) && (CSR[misa].F == 1'b0)) { + # must be read-only-0 + return 0; + } else { + # there will be no hardware update in this case because we know the F extension isn't implemented + return ary_includes?<$array_size(MSTATUS_FS_LEGAL_VALUES), 2>(MSTATUS_FS_LEGAL_VALUES, csr_value.FS) ? csr_value.FS : UNDEFINED_LEGAL_DETERMINISTIC; + } + MPP: + location: 12-11 + description: | + M-mode Previous Privilege. + + Written by hardware in two cases: + + * Written with the prior nominal privilege level when entering M-mode from an exception/interrupt. + * Written with 0 when executing an `mret` instruction to return from an exception in M-mode. + + Can also be written by software without immediate side-effect. + + Affects execution in two cases: + + * On a return from an exception from M-mode, the machine will + enter the privilege level stored in MPP before clearing the field. + * When `mstatus.MPRV` is set, loads and stores behave as if the current privlege level were MPP. + type: RW-H + reset_value: UNDEFINED_LEGAL + sw_write(csr_value): | + if (csr_value.MPP == 2'b01 && !implemented?(ExtensionName::S)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (csr_value.MPP == 2'b00 && !implemented?(ExtensionName::U)) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else if (csr_value.MPP == 2'b10) { + # never a valid value + return UNDEFINED_LEGAL_DETERMINISTIC; + } else { + return csr_value.MPP; + } + legal?(csr_value): | + if (csr_value.MPP == 2'b01 && !implemented?(ExtensionName::S)) { + return false; + } else if (csr_value.MPP == 2'b00 && !implemented?(ExtensionName::U)) { + return false; + } else if (csr_value.MPP == 2'b10) { + # never a valid value + return flase; + } else { + return true; + } + VS: + location: 10-9 + description: | + Vector context status. + + When 0, vector instructions (from the V extension) are disabled, and cause ILLEGAL INSTRUCTION exceptions. + When a vector register or vector CSR is written, VS obtains the value 3. + Values 1 and 2 are valid write values for software, but are not interpreted by hardware + other than to possibly enable a previously-disabled vector unit. + definedBy: + anyOf: [V, S] + type(): | + if (CSR[misa].V == 1'b1){ + return CsrFieldType::RWH; + } else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) { + # must be read-only-0 + return CsrFieldType::RO; + } else { + # there will be no hardware update in this case because we know the V extension isn't implemented + return MSTATUS_VS_WRITEABLE ? CsrFieldType::RW : CsrFieldType::RO; + } + reset_value(): | + if (CSR[misa].V == 1'b1){ + return UNDEFINED_LEGAL; + } else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) { + # must be read-only-0 + return 0; + } else { + # there will be no hardware update in this case because we know the V extension isn't implemented + return MSTATUS_VS_WRITEABLE ? UNDEFINED_LEGAL : 0; + } + sw_write(csr_value): | + if (CSR[misa].V == 1'b1){ + return ary_includes?<$array_size(MSTATUS_VS_LEGAL_VALUES), 2>(MSTATUS_VS_LEGAL_VALUES, csr_value.FS) ? csr_value.FS : UNDEFINED_LEGAL_DETERMINISTIC; + } else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) { + # must be read-only-0 + return 0; + } else { + # there will be no hardware update in this case because we know the V extension isn't implemented + return ary_includes?<$array_size(MSTATUS_VS_LEGAL_VALUES), 2>(MSTATUS_VS_LEGAL_VALUES, csr_value.FS) ? csr_value.FS : UNDEFINED_LEGAL_DETERMINISTIC; + } + SPP: + location: 8 + description: | + *S-mode Previous Privilege* + + Written by hardware in two cases: + + * Written with the prior nominal privilege level when entering (H)S-mode from an exception/interrupt. + * Written with 0 when executing an `sret` instruction to return from an exception in (H)S-mode or (unlikely) M-mode. + + Can also be written by software without immediate side-effect. + + Affects execution in one case: + + * On a return from an exception using the `sret` instruction in (H)S-mode or (unlikely) M-mode, + the machine will enter the privilege level stored in SPP before clearing the field. + + Notably, `mstatus.SPP` does not affect exception return in VS-mode (see `vsstatus.SPP`). + + type: RW-H + definedBy: S + reset_value: UNDEFINED_LEGAL + sw_write(csr_value): | + if (csr_value.SPP == 2'b10) { + return UNDEFINED_LEGAL_DETERMINISTIC; + } else { + return csr_value.SPP; + } + legal?(csr_value): | + return csr_value.SPP != 2'b10; + MPIE: + location: 7 + description: | + *M-mode Previous Interrupt Enable* + + Written by hardware in two cases: + + * Written with prior value of `mstatus.MIE` when entering M-mode from an exception/interrupt. + * Writen with the value 1 when returning from an exception in M-mode (via the `mret` instruction). + + Can also be written by software without immediate side effect. + + Other than serving as a record of nested traps as described above, `mstatus.MPIE` does not affect execution. + + type: RW-H + reset_value: UNDEFINED_LEGAL + UBE: + location: 6 + definedBy: U + description: | + *U-mode Big Endian* + + Controls the endianness of U-mode (0 = little, 1 = big). + Instructions are always little endian, regardless of the data setting. + + [when,"U_MODE_ENDIANESS == 'little'"] + Since the CPU does not support big endian in U-mode, this is hardwired to 0. + + [when,"U_MODE_ENDIANESS == 'big'"] + Since the CPU does not support litte endian in U-mode, this is hardwired to 1. + type(): | + return (U_MODE_ENDIANESS == "dynamic") ? CsrFieldType::RW : CsrFieldType::RO; + + reset_value(): | + if (U_MODE_ENDIANESS == "little") { + return 0; + } else if (U_MODE_ENDIANESS == "big") { + return 1; + } else { + return UNDEFINED_LEGAL; + } + + SPIE: + location: 5 + description: | + *S-mode Previous Interrupt Enable* + + Written by hardware in two cases: + + * Written with prior value of `mstatus.SIE` when entering (H)S-mode from an exception/interrupt. + * Writen with the value 1 when returning from an exception via the `sret` instruction in (H)S-mode or (unlikely) M-mode. + + Can also be written by software without immediate side effect. + + Other than serving as a record of nested traps as described above, `mstatus.SPIE` does not affect execution. + type(): | + return (CSR[misa].S == 1'b1) ? CsrFieldType::RWH : CsrFieldType::RO; + definedBy: S + reset_value(): | + return (CSR[misa].S == 1'b1) ? UNDEFINED_LEGAL : 0; + MIE: + location: 3 + description: | + *M-mode Interrupt Enable* + + Written by hardware in two cases: + + * Written with the value 0 when entering M-mode from an exception/interrupt. + * Written with the prior value of `mstatus.MPIE` when returning from an exeception in M-mode (via `mret`). + + Affects execution by: + + * When 0, all interrupts are disabled when the current privilege level is M. + * When 1, interrupts that are not otherwise disabled with a field in `mie` are enabled. + + type: RW-H + reset_value: 0 + SIE: + location: 1 + description: | + *S-mode Interrupt Enable* + + Written by hardware in two cases: + + * Written with the value 0 when entering (H)S-mode from an exception/interrupt. + * Written with the prior value of `mstatus.SPIE` when returning from an exeception via `sret` in (H)S-mode or (unlikely) M-mode. + + Affects execution by: + + * When 0, all (H)S-mode interrupts are disabled when the current privilege level is (H)S (M-mode interrupts are still enabled). + * When 1, (H)S-mode interrupts that are not otherwise disabled with a field in `sie` are enabled. + + type(): | + return (CSR[misa].S == 1'b1) ? CsrFieldType::RWH : CsrFieldType::RO; + definedBy: S + reset_value(): | + return (CSR[misa].S == 1'b1) ? UNDEFINED_LEGAL : 0; diff --git a/arch/csr/mstatush.yaml b/arch/csr/mstatush.yaml index eec243033..329d2a99e 100644 --- a/arch/csr/mstatush.yaml +++ b/arch/csr/mstatush.yaml @@ -1,56 +1,58 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mstatush: - long_name: Machine Status High - address: 0x310 - priv_mode: M - base: 32 - length: 32 - description: The mstatus register tracks and controls the hart's current operating state. - definedBy: - name: Sm - version: ">= 1.12" - fields: - MPV: - location: 7 - description: | - *Machine Previous Virtualization mode* +$schema: "csr_schema.json#" +kind: csr +name: mstatush +long_name: Machine Status High +address: 0x310 +priv_mode: M +base: 32 +length: 32 +description: The mstatus register tracks and controls the hart's current operating state. +definedBy: + name: Sm + version: ">= 1.12" +fields: + MPV: + location: 7 + description: | + *Machine Previous Virtualization mode* - Written with the prior virtualization mode when entering M-mode from an exception/interrupt. - When returning via an MRET instruction, the virtualization mode becomes the value of MPV unless MPP=3, in which case the virtualization mode is always 0. - Can also be written by software. - type: RW-H - reset_value: UNDEFINED_LEGAL - definedBy: H - GVA: - location: 6 - description: | - *Guest Virtual Address* + Written with the prior virtualization mode when entering M-mode from an exception/interrupt. + When returning via an MRET instruction, the virtualization mode becomes the value of MPV unless MPP=3, in which case the virtualization mode is always 0. + Can also be written by software. + type: RW-H + reset_value: UNDEFINED_LEGAL + definedBy: H + GVA: + location: 6 + description: | + *Guest Virtual Address* - When a trap is taken and a guest virtual address is written into mtval, GVA is set. - When a trap is taken and a guest virtual address is written into mtval, GVA is cleared. - type: RW-H - reset_value: 0 - definedBy: H - MBE: - location: 5 - description: | - see `mstatus.MBE` - type(): 'return (M_MODE_ENDIANESS == "dynamic") ? CsrFieldType::RW : CsrFieldType::RO;' - reset_value(): 'return (M_MODE_ENDIANESS == "big") ? 1 : 0;' - alias: mstatus.MBE - SBE: - location: 4 - definedBy: S - description: | - see `mstatus.SBE` - type(): 'return (S_MODE_ENDIANESS == "dynamic") ? CsrFieldType::RW : CsrFieldType::RO;' - reset_value(): | - if (S_MODE_ENDIANESS == "little") { - return 0; - } else if (S_MODE_ENDIANESS == "big") { - return 1; - } else { - return UNDEFINED_LEGAL; - } + When a trap is taken and a guest virtual address is written into mtval, GVA is set. + When a trap is taken and a guest virtual address is written into mtval, GVA is cleared. + type: RW-H + reset_value: 0 + definedBy: H + MBE: + location: 5 + description: | + see `mstatus.MBE` + type(): 'return (M_MODE_ENDIANESS == "dynamic") ? CsrFieldType::RW : CsrFieldType::RO;' + reset_value(): 'return (M_MODE_ENDIANESS == "big") ? 1 : 0;' + alias: mstatus.MBE + SBE: + location: 4 + definedBy: S + description: | + see `mstatus.SBE` + type(): 'return (S_MODE_ENDIANESS == "dynamic") ? CsrFieldType::RW : CsrFieldType::RO;' + reset_value(): | + if (S_MODE_ENDIANESS == "little") { + return 0; + } else if (S_MODE_ENDIANESS == "big") { + return 1; + } else { + return UNDEFINED_LEGAL; + } diff --git a/arch/csr/mtval.yaml b/arch/csr/mtval.yaml index c812bda4d..e2d4da1a0 100644 --- a/arch/csr/mtval.yaml +++ b/arch/csr/mtval.yaml @@ -1,97 +1,99 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mtval: - long_name: Machine Trap Value - address: 0x343 - description: Holds trap-specific information - priv_mode: M - length: MXLEN - definedBy: Sm - fields: - VALUE: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Written with trap-specific information when a trap is taken into M-mode. +$schema: "csr_schema.json#" +kind: csr +name: mtval +long_name: Machine Trap Value +address: 0x343 +description: Holds trap-specific information +priv_mode: M +length: MXLEN +definedBy: Sm +fields: + VALUE: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Written with trap-specific information when a trap is taken into M-mode. - The values are: + The values are: - [separator="!"] - !=== - ! Exception type ! Value + [separator="!"] + !=== + ! Exception type ! Value - ! [0] Instruction address misaligned ! The misaligned virtual PC (same as the value written to `mepc`). - ! [1] Instruction access fault ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the access fault <%- unless ext?(:C) -%>(same as the value written to `mepc`)<%- end -%>. - ! [2] Illegal Instruction ! The encoding of the illegal instruction. - ! [3] Breakpoint - ! [when,"REPORT_VA_IN_MTVAL_ON_BREAKPOINT == true"] - When caused by an EBREAK instruction, the virtual PC of the breakpoint instruction. + ! [0] Instruction address misaligned ! The misaligned virtual PC (same as the value written to `mepc`). + ! [1] Instruction access fault ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the access fault <%- unless ext?(:C) -%>(same as the value written to `mepc`)<%- end -%>. + ! [2] Illegal Instruction ! The encoding of the illegal instruction. + ! [3] Breakpoint + ! [when,"REPORT_VA_IN_MTVAL_ON_BREAKPOINT == true"] + When caused by an EBREAK instruction, the virtual PC of the breakpoint instruction. - [when,"REPORT_VA_IN_MTVAL_ON_BREAKPOINT == false"] - When caused by an EBREAK instruction, zero. + [when,"REPORT_VA_IN_MTVAL_ON_BREAKPOINT == false"] + When caused by an EBREAK instruction, zero. - When caused by a data address (_i.e._, watchpoint) breakpoint, the faulting virtual address. - When caused by an instruction address breakpoint, the faulting virtual PC. - ! [4] Load address misaligned ! The misaligned virtual load address. - ! [5] Load access fault - ! The part of virtual load address causing in the access fault. + When caused by a data address (_i.e._, watchpoint) breakpoint, the faulting virtual address. + When caused by an instruction address breakpoint, the faulting virtual PC. + ! [4] Load address misaligned ! The misaligned virtual load address. + ! [5] Load access fault + ! The part of virtual load address causing in the access fault. - When the load is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, - address + 4 is reported). + When the load is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, + address + 4 is reported). - (Even though the access fault arises on a physical address, the virtual address is reported) - ! [6] Store/AMO address misaligned ! The misaligned virtual store/AMO address. - ! [7] Store/AMO access fault - ! The virtual store/AMO address causing the access fault. - - When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, - address + 4 is reported). + (Even though the access fault arises on a physical address, the virtual address is reported) + ! [6] Store/AMO address misaligned ! The misaligned virtual store/AMO address. + ! [7] Store/AMO access fault + ! The virtual store/AMO address causing the access fault. + + When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, + address + 4 is reported). - (Even though the access fault arises on a physical address, the virtual address is reported) - ! [8] Environment call from U-mode <% if ext?(:H) %>or VU-mode<% end %> ! Zero - ! [9] Environment call from (H)S-mode ! Zero - <%- if ext?(:H) -%> - ! [10] Environment call from VS-mode ! Zero - <%- end -%> - ! [11] Environment call from M-mode ! Zero - ! [12] Instruction page fault - ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the page fault - <% unless ext?(:C) %>(same as the value written to `mepc`)<% end %>. - ! [13] Load page fault - ! The part of the virtual load address causing in the page fault. - - When the load is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, address + 4 is reported). - ! [15] Store/AMO page fault - ! The virtual store/AMO address causing in the page fault. - - When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, address + 4 is reported). - <%- if ext?(:H) -%> - ! [20] Instruction guest-page fault - ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the fault <% unless ext?(:C) %>(same as the value written to `mepc`)<% end %>. + (Even though the access fault arises on a physical address, the virtual address is reported) + ! [8] Environment call from U-mode <% if ext?(:H) %>or VU-mode<% end %> ! Zero + ! [9] Environment call from (H)S-mode ! Zero + <%- if ext?(:H) -%> + ! [10] Environment call from VS-mode ! Zero + <%- end -%> + ! [11] Environment call from M-mode ! Zero + ! [12] Instruction page fault + ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the page fault + <% unless ext?(:C) %>(same as the value written to `mepc`)<% end %>. + ! [13] Load page fault + ! The part of the virtual load address causing in the page fault. + + When the load is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, address + 4 is reported). + ! [15] Store/AMO page fault + ! The virtual store/AMO address causing in the page fault. - The guest physical address is reported in `mtval2`. - ! [21] Load guest-page fault - ! The part of the virtual address causing the fault. + When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, address + 4 is reported). + <%- if ext?(:H) -%> + ! [20] Instruction guest-page fault + ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the fault <% unless ext?(:C) %>(same as the value written to `mepc`)<% end %>. + + The guest physical address is reported in `mtval2`. + ! [21] Load guest-page fault + ! The part of the virtual address causing the fault. - When the load is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, address + 4 is reported). - - The guest physical address is reported in `mtval2`. - ! [22] Virutal instruction - ! The encoding of the faulting virtual instruction. - ! [23] Store/AMO guest-page fault - ! The part of the virtual address causing the fault. + When the load is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, address + 4 is reported). + + The guest physical address is reported in `mtval2`. + ! [22] Virutal instruction + ! The encoding of the faulting virtual instruction. + ! [23] Store/AMO guest-page fault + ! The part of the virtual address causing the fault. + + When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, address + 4 is reported). - When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, address + 4 is reported). - - The guest physical address is reported in `mtval2`. - <%- end -%> - !=== + The guest physical address is reported in `mtval2`. + <%- end -%> + !=== - type: RW-H - reset_value: 0 + type: RW-H + reset_value: 0 diff --git a/arch/csr/mtvec.yaml b/arch/csr/mtvec.yaml index e5ec8e323..f38a48b8c 100644 --- a/arch/csr/mtvec.yaml +++ b/arch/csr/mtvec.yaml @@ -1,55 +1,56 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mtvec: - long_name: Machine Trap Vector Control - address: 0x305 - priv_mode: M - length: MXLEN - description: Controls where traps jump. - definedBy: Sm - fields: - BASE: - location_rv64: 63-2 - location_rv32: 31-2 - description: | - Bits [MXLEN-1:2] of the exception vector physical address for any trap taken in M-mode. +$schema: "csr_schema.json#" +kind: csr +name: mtvec +long_name: Machine Trap Vector Control +address: 0x305 +priv_mode: M +length: MXLEN +description: Controls where traps jump. +definedBy: Sm +fields: + BASE: + location_rv64: 63-2 + location_rv32: 31-2 + description: | + Bits [MXLEN-1:2] of the exception vector physical address for any trap taken in M-mode. - The implementation physical memory map may resitrict which values are legal in this field. - type: RW-R - sw_write(csr_value): | - # Base spec says that BASE must be 4-byte aligned, which will always be the case - # implementations may put further constraints on BASE when MODE != Direct - # If that is the case, stvec should have an override for the implementation - return csr_value.BASE; - reset_value: 0 - MODE: - location: 1-0 - description: | - Vectoring mode for asynchronous interrupts. - - 0 - Direct, 1 - Vectored + The implementation physical memory map may resitrict which values are legal in this field. + type: RW-R + sw_write(csr_value): | + # Base spec says that BASE must be 4-byte aligned, which will always be the case + # implementations may put further constraints on BASE when MODE != Direct + # If that is the case, stvec should have an override for the implementation + return csr_value.BASE; + reset_value: 0 + MODE: + location: 1-0 + description: | + Vectoring mode for asynchronous interrupts. + + 0 - Direct, 1 - Vectored - When Direct, all synchronous exceptions and asynchronous interrupts jump to (`mtvec.BASE` << 2). + When Direct, all synchronous exceptions and asynchronous interrupts jump to (`mtvec.BASE` << 2). - When Vectored, asynchronous interrupts jump to (`mtvec.BASE` << 2 + `mcause.CAUSE`*4) while synchronous exceptions continue to jump to (`mtvec.BASE` << 2). - - type(): | - return ($array_size(MTVEC_MODES) == 1) ? CsrFieldType::RO : CsrFieldType::RWR; - sw_write(csr_value): | - if (csr_value.MODE == 0) { - if (ary_includes?<$array_size(MTVEC_MODES), 2>(MTVEC_MODES, 0)) { - return csr_value.MODE; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } - } else if (csr_value.MODE == 1) { - if (ary_includes?<$array_size(MTVEC_MODES), 2>(MTVEC_MODES, 1)) { - return csr_value.MODE; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + When Vectored, asynchronous interrupts jump to (`mtvec.BASE` << 2 + `mcause.CAUSE`*4) while synchronous exceptions continue to jump to (`mtvec.BASE` << 2). + type(): | + return ($array_size(MTVEC_MODES) == 1) ? CsrFieldType::RO : CsrFieldType::RWR; + sw_write(csr_value): | + if (csr_value.MODE == 0) { + if (ary_includes?<$array_size(MTVEC_MODES), 2>(MTVEC_MODES, 0)) { + return csr_value.MODE; } else { return UNDEFINED_LEGAL_DETERMINISTIC; } - reset_value(): | - return ($array_size(MTVEC_MODES) == 1) ? MTVEC_MODES[0] : UNDEFINED_LEGAL; + } else if (csr_value.MODE == 1) { + if (ary_includes?<$array_size(MTVEC_MODES), 2>(MTVEC_MODES, 1)) { + return csr_value.MODE; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } + reset_value(): | + return ($array_size(MTVEC_MODES) == 1) ? MTVEC_MODES[0] : UNDEFINED_LEGAL; diff --git a/arch/csr/mvendorid.yaml b/arch/csr/mvendorid.yaml index 29dc3a009..a752ece2d 100644 --- a/arch/csr/mvendorid.yaml +++ b/arch/csr/mvendorid.yaml @@ -1,20 +1,22 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -mvendorid: - long_name: Machine Vendor ID - address: 0xf11 - priv_mode: M - length: 32 - description: Reports the JEDEC manufacturer ID of the core. - fields: - Bank: - description: JEDEC manufacturer ID bank minus 1 - location: 31-7 - type: RO - reset_value(): return VENDOR_ID_BANK; - Offset: - description: JEDEC manufacturer ID offset - location: 6-0 - type: RO - reset_value(): return VENDOR_ID_OFFSET; - definedBy: Sm +$schema: "csr_schema.json#" +kind: csr +name: mvendorid +long_name: Machine Vendor ID +address: 0xf11 +priv_mode: M +length: 32 +description: Reports the JEDEC manufacturer ID of the core. +fields: + Bank: + description: JEDEC manufacturer ID bank minus 1 + location: 31-7 + type: RO + reset_value(): return VENDOR_ID_BANK; + Offset: + description: JEDEC manufacturer ID offset + location: 6-0 + type: RO + reset_value(): return VENDOR_ID_OFFSET; +definedBy: Sm diff --git a/arch/csr/satp.yaml b/arch/csr/satp.yaml index 28906d04e..b4d4a0d3a 100644 --- a/arch/csr/satp.yaml +++ b/arch/csr/satp.yaml @@ -1,162 +1,164 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -satp: - address: 0x180 - long_name: Supervisor Address Translation and Protection - description: Controls the translation mode in (H)S-mode and U-mode, and holds the current ASID and page table base pointer. - priv_mode: S - length: SXLEN - definedBy: S - fields: - MODE: - location_rv64: 63-60 - location_rv32: 31 - type: RW-R - description: | - *Translation Mode* - - Controls the current translation mode according to the table below. - - [separator="!",%autowidth] - !=== - ! Value ! Name ! Description - - ! 0 ! Bare a! No translation -> virtual address == physical address - <%- if ext?(:Sv39) -%> - ! 8 ! Sv39 ! 39-bit virtual address translation - <%- end -%> - <%- if ext?(:Sv48) -%> - ! 9 ! Sv48 ! 48-bit virtual address translation - <%- end -%> - <%- if ext?(:Sv57) -%> - ! 10 ! Sv57 ! 57-bit virtual address translation - <%- end -%> - !=== - - Any other value shall be ignored on a write. - reset_value: UNDEFINED_LEGAL - sw_write(csr_value): | - if (SATP_MODE_BARE) { - if (csr_value.MODE == 0) { - # In Bare, ASID and PPN must be zero, else the entire write is ignored - if (csr_value.ASID == 0 && csr_value.PPN == 0) { - if (CSR[satp].MODE != 0) { - # changes *to* Bare mode take effect immediately without needing sfence.vma - # thus, an implicit sfence.vma occurs now - VmaOrderType order_type; - order_type.global = true; - order_pgtbl_writes_before_vmafence(order_type); - - invalidate_translations(order_type); - - order_pgtbl_reads_after_vmafence(order_type); - } - return csr_value.MODE; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } - } - } - else if (implemented?(ExtensionName::Sv39) && csr_value.MODE == 8) { - if (CSR[satp].MODE == 0) { - # changes *from* Bare mode take effect immediately without needing sfence.vma - # thus, an implicit sfence.vma occurs now - VmaOrderType order_type; - order_type.global = true; - order_pgtbl_writes_before_vmafence(order_type); +$schema: "csr_schema.json#" +kind: csr +name: satp +address: 0x180 +long_name: Supervisor Address Translation and Protection +description: Controls the translation mode in (H)S-mode and U-mode, and holds the current ASID and page table base pointer. +priv_mode: S +length: SXLEN +definedBy: S +fields: + MODE: + location_rv64: 63-60 + location_rv32: 31 + type: RW-R + description: | + *Translation Mode* + + Controls the current translation mode according to the table below. + + [separator="!",%autowidth] + !=== + ! Value ! Name ! Description + + ! 0 ! Bare a! No translation -> virtual address == physical address + <%- if ext?(:Sv39) -%> + ! 8 ! Sv39 ! 39-bit virtual address translation + <%- end -%> + <%- if ext?(:Sv48) -%> + ! 9 ! Sv48 ! 48-bit virtual address translation + <%- end -%> + <%- if ext?(:Sv57) -%> + ! 10 ! Sv57 ! 57-bit virtual address translation + <%- end -%> + !=== + + Any other value shall be ignored on a write. + reset_value: UNDEFINED_LEGAL + sw_write(csr_value): | + if (SATP_MODE_BARE) { + if (csr_value.MODE == 0) { + # In Bare, ASID and PPN must be zero, else the entire write is ignored + if (csr_value.ASID == 0 && csr_value.PPN == 0) { + if (CSR[satp].MODE != 0) { + # changes *to* Bare mode take effect immediately without needing sfence.vma + # thus, an implicit sfence.vma occurs now + VmaOrderType order_type; + order_type.global = true; + order_pgtbl_writes_before_vmafence(order_type); - invalidate_translations(order_type); + invalidate_translations(order_type); - order_pgtbl_reads_after_vmafence(order_type); + order_pgtbl_reads_after_vmafence(order_type); + } + return csr_value.MODE; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; } - return csr_value.MODE; } - else if (implemented?(ExtensionName::Sv48) && csr_value.MODE == 9) { - if (CSR[satp].MODE == 0) { - # changes *from* Bare mode take effect immediately without needing sfence.vma - # thus, an implicit sfence.vma occurs now - VmaOrderType order_type; - order_type.global = true; - order_pgtbl_writes_before_vmafence(order_type); - - invalidate_translations(order_type); - - order_pgtbl_reads_after_vmafence(order_type); - } - - return csr_value.MODE; + } + else if (implemented?(ExtensionName::Sv39) && csr_value.MODE == 8) { + if (CSR[satp].MODE == 0) { + # changes *from* Bare mode take effect immediately without needing sfence.vma + # thus, an implicit sfence.vma occurs now + VmaOrderType order_type; + order_type.global = true; + order_pgtbl_writes_before_vmafence(order_type); + + invalidate_translations(order_type); + + order_pgtbl_reads_after_vmafence(order_type); + } + return csr_value.MODE; + } + else if (implemented?(ExtensionName::Sv48) && csr_value.MODE == 9) { + if (CSR[satp].MODE == 0) { + # changes *from* Bare mode take effect immediately without needing sfence.vma + # thus, an implicit sfence.vma occurs now + VmaOrderType order_type; + order_type.global = true; + order_pgtbl_writes_before_vmafence(order_type); + + invalidate_translations(order_type); + + order_pgtbl_reads_after_vmafence(order_type); } - else if (implemented?(ExtensionName::Sv57) && csr_value.MODE == 10) { - if (CSR[satp].MODE == 0) { - # changes *from* Bare mode take effect immediately without needing sfence.vma - # thus, an implicit sfence.vma occurs now - VmaOrderType order_type; - order_type.global = true; - order_pgtbl_writes_before_vmafence(order_type); - invalidate_translations(order_type); + return csr_value.MODE; + } + else if (implemented?(ExtensionName::Sv57) && csr_value.MODE == 10) { + if (CSR[satp].MODE == 0) { + # changes *from* Bare mode take effect immediately without needing sfence.vma + # thus, an implicit sfence.vma occurs now + VmaOrderType order_type; + order_type.global = true; + order_pgtbl_writes_before_vmafence(order_type); - order_pgtbl_reads_after_vmafence(order_type); - } + invalidate_translations(order_type); - return csr_value.MODE; + order_pgtbl_reads_after_vmafence(order_type); } - else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } - ASID: - location_rv32: 30-22 - location_rv64: 59-44 - description: | - *Address Space ID* - type: RW-R - sw_write(csr_value): | - if (csr_value.MODE == 0) { - # when MODE == Bare, PPN and ASID must be zero - if (csr_value.ASID == 0 && csr_value.PPN == 0) { - return csr_value.ASID; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + + return csr_value.MODE; + } + else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } + ASID: + location_rv32: 30-22 + location_rv64: 59-44 + description: | + *Address Space ID* + type: RW-R + sw_write(csr_value): | + if (csr_value.MODE == 0) { + # when MODE == Bare, PPN and ASID must be zero + if (csr_value.ASID == 0 && csr_value.PPN == 0) { + return csr_value.ASID; } else { - XReg shamt = (XLEN == 32 || (CSR[mstatus].SXL == $bits(XRegWidth::XLEN32))) ? 9 : 16; - XReg all_ones = ((1 << shamt) - 1); - XReg largest_allowed_asid = (1 << shamt) - 1; - - if (csr_value.ASID == all_ones) { - # the specification states that if all 1's are written to the ASID field, then - # you must return the largest asid - return largest_allowed_asid; - } else if (csr_value.ASID > largest_allowed_asid) { - # ... but is silent on what happens on any other illegal value - return UNDEFINED_LEGAL_DETERMINISTIC; - } else { - # unrestricted - return csr_value.ASID; - } + return UNDEFINED_LEGAL_DETERMINISTIC; } - reset_value: UNDEFINED_LEGAL - PPN: - location_rv32: 21-0 - location_rv64: 43-0 - description: | - *Physical Page Number* - - The physical address of the active root page table is PPN << 12. - - Can only hold values that correspond to a valid page table base, which - will be implementation-dependent. - type: RW-R - reset_value: UNDEFINED_LEGAL - sw_write(csr_value): | - if (csr_value.MODE == 0) { - # when MODE == Bare, PPN and ASID must be zero - if (csr_value.ASID == 0 && csr_value.PPN == 0) { - return csr_value.PPN; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } + } else { + XReg shamt = (XLEN == 32 || (CSR[mstatus].SXL == $bits(XRegWidth::XLEN32))) ? 9 : 16; + XReg all_ones = ((1 << shamt) - 1); + XReg largest_allowed_asid = (1 << shamt) - 1; + + if (csr_value.ASID == all_ones) { + # the specification states that if all 1's are written to the ASID field, then + # you must return the largest asid + return largest_allowed_asid; + } else if (csr_value.ASID > largest_allowed_asid) { + # ... but is silent on what happens on any other illegal value + return UNDEFINED_LEGAL_DETERMINISTIC; } else { # unrestricted + return csr_value.ASID; + } + } + reset_value: UNDEFINED_LEGAL + PPN: + location_rv32: 21-0 + location_rv64: 43-0 + description: | + *Physical Page Number* + + The physical address of the active root page table is PPN << 12. + + Can only hold values that correspond to a valid page table base, which + will be implementation-dependent. + type: RW-R + reset_value: UNDEFINED_LEGAL + sw_write(csr_value): | + if (csr_value.MODE == 0) { + # when MODE == Bare, PPN and ASID must be zero + if (csr_value.ASID == 0 && csr_value.PPN == 0) { return csr_value.PPN; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; } + } else { + # unrestricted + return csr_value.PPN; + } diff --git a/arch/csr/scause.yaml b/arch/csr/scause.yaml index 54816fcfb..21b8b4a54 100644 --- a/arch/csr/scause.yaml +++ b/arch/csr/scause.yaml @@ -1,89 +1,91 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -scause: - long_name: Supervisor Cause - address: 0x142 - priv_mode: S - length: SXLEN - description: Reports the cause of the latest exception. - definedBy: S - fields: - INT: - location_rv32: 31 - location_rv64: 63 - description: | - Written by hardware when a trap is taken into S-mode. - - When set, the last exception was caused by an asynchronous Interrupt. +$schema: "csr_schema.json#" +kind: csr +name: scause +long_name: Supervisor Cause +address: 0x142 +priv_mode: S +length: SXLEN +description: Reports the cause of the latest exception. +definedBy: S +fields: + INT: + location_rv32: 31 + location_rv64: 63 + description: | + Written by hardware when a trap is taken into S-mode. + + When set, the last exception was caused by an asynchronous Interrupt. - `scause.INT` is writeable. + `scause.INT` is writeable. - [when,"TRAP_ON_ILLEGAL_WLRL == true"] - If `scause` is written with an undefined cause (combination of `scause.INT` and `scause.CODE`), an `Illegal Instruction` exception occurs. + [when,"TRAP_ON_ILLEGAL_WLRL == true"] + If `scause` is written with an undefined cause (combination of `scause.INT` and `scause.CODE`), an `Illegal Instruction` exception occurs. - [when,"TRAP_ON_ILLEGAL_WLRL == false"] - If `scause` is written with an undefined cause (combination of `scause.INT` and `scause.CODE`), neither `scause.INT` nor `scause.CODE` are modified. - type: RW-RH - sw_write(csr_value): | - # the write only holds if the INT/CODE combination is valid - # otherwise, the old value is retained - if (csr_value.INT == 1) { - if (valid_interrupt_code?(csr_value.CODE)) { - return 1; - } - return ILLEGAL_WLRL; - } else { - if (valid_exception_code?(csr_value.CODE)) { - return 1; - } - return ILLEGAL_WLRL; + [when,"TRAP_ON_ILLEGAL_WLRL == false"] + If `scause` is written with an undefined cause (combination of `scause.INT` and `scause.CODE`), neither `scause.INT` nor `scause.CODE` are modified. + type: RW-RH + sw_write(csr_value): | + # the write only holds if the INT/CODE combination is valid + # otherwise, the old value is retained + if (csr_value.INT == 1) { + if (valid_interrupt_code?(csr_value.CODE)) { + return 1; } - reset_value: UNDEFINED_LEGAL - CODE: - location_rv32: 30-0 - location_rv64: 62-0 - description: | - Written by hardware when a trap is taken into S-mode. + return ILLEGAL_WLRL; + } else { + if (valid_exception_code?(csr_value.CODE)) { + return 1; + } + return ILLEGAL_WLRL; + } + reset_value: UNDEFINED_LEGAL + CODE: + location_rv32: 30-0 + location_rv64: 62-0 + description: | + Written by hardware when a trap is taken into S-mode. - Holds the interrupt or exception code for the last taken trap. + Holds the interrupt or exception code for the last taken trap. - `scause.CODE` is writeable. + `scause.CODE` is writeable. - [when,"TRAP_ON_ILLEGAL_WLRL == true"] - If `scause` is written with an undefined cause (combination of `scause.INT` and `scause.CODE`), an `Illegal Instruction` exception occurs. + [when,"TRAP_ON_ILLEGAL_WLRL == true"] + If `scause` is written with an undefined cause (combination of `scause.INT` and `scause.CODE`), an `Illegal Instruction` exception occurs. - [when,"TRAP_ON_ILLEGAL_WLRL == false"] - If `scause` is written with an undefined cause (combination of `scause.INT` and `scause.CODE`), neither `scause.INT` nor `scause.CODE` are modified. + [when,"TRAP_ON_ILLEGAL_WLRL == false"] + If `scause` is written with an undefined cause (combination of `scause.INT` and `scause.CODE`), neither `scause.INT` nor `scause.CODE` are modified. - Valid interrupt codes are: - [separator="!"] - !=== - <%- interrupt_codes.sort_by { |code| code.num }.each do |code| -%> - ! <%= code.num %> ! <%= code.name %> - <%- end -%> - !=== + Valid interrupt codes are: + [separator="!"] + !=== + <%- interrupt_codes.sort_by { |code| code.num }.each do |code| -%> + ! <%= code.num %> ! <%= code.name %> + <%- end -%> + !=== - Valid exception codes are: - [separator="!"] - !=== - <%- exception_codes.sort_by { |code| code.num }.each do |code| -%> - ! <%= code.num %> ! <%= code.name %> - <%- end -%> - !=== - type: RW-RH - sw_write(csr_value): | - # the write only holds if the INT/CODE combination is valid - # otherwise, the old value is retained - if (csr_value.INT == 1) { - if (valid_interrupt_code?(csr_value.CODE)) { - return csr_value.CODE; - } - return ILLEGAL_WLRL; - } else { - if (valid_exception_code?(csr_value.CODE)) { - return csr_value.CODE; - } - return ILLEGAL_WLRL; + Valid exception codes are: + [separator="!"] + !=== + <%- exception_codes.sort_by { |code| code.num }.each do |code| -%> + ! <%= code.num %> ! <%= code.name %> + <%- end -%> + !=== + type: RW-RH + sw_write(csr_value): | + # the write only holds if the INT/CODE combination is valid + # otherwise, the old value is retained + if (csr_value.INT == 1) { + if (valid_interrupt_code?(csr_value.CODE)) { + return csr_value.CODE; + } + return ILLEGAL_WLRL; + } else { + if (valid_exception_code?(csr_value.CODE)) { + return csr_value.CODE; } - reset_value: UNDEFINED_LEGAL + return ILLEGAL_WLRL; + } + reset_value: UNDEFINED_LEGAL diff --git a/arch/csr/senvcfg.yaml b/arch/csr/senvcfg.yaml index 032fc52e0..e804e5aae 100644 --- a/arch/csr/senvcfg.yaml +++ b/arch/csr/senvcfg.yaml @@ -1,143 +1,145 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -senvcfg: - address: 0x10A - long_name: Supervisor Environment Configuration - description: Contains bits to enable/disable extensions - priv_mode: S - length: 64 - definedBy: - allOf: - - name: Sm - version: ">=1.12" - - name: S - fields: - CBZE: - location: 7 - description: | - *Cache Block Zero instruction Enable* - - Bit is read-only 0 when `menvcfg.CBZE` is clear. - - Enables the execution of the cache block zero instruction, `cbo.zero`, - in U-mode<% if ext?(:H) %> and (in conjunction with `henvcfg.CBZE`) VU-mode<% end %>. - - * `0`: The instruction raises an illegal instruction<% if ext?(:H) %> or virtual instruction exception<% end %> - * `1`: The instruction is executed - - To summarize access: - [separator="!",%autowidth] - !=== - ! `menvcfg.CBZE` ! `senvcfg.CBZE` behavior - - ! 0 ! read-only 0 - ! 1 - a! writeable, independent bit from `menvcfg.CBZE` - !=== - - See `cbo.zero` for a summary of the effect. - - definedBy: Zicboz - type: RW - reset_value: UNDEFINED_LEGAL - CBCFE: - location: 6 - description: | - *Cache Block Clean and Flush instruction Enable* - - Enables the execution of the cache block clean instruction, `cbo.clean`, and the - cache block flush instruction, `cbo.flush`, - <% if ext?(:S) %> - in S-mode - <% elsif ext?(:U) %> - in U-mode - <% end %>. - - * `0`: The instruction raises an illegal instruction <% if ext?(:H) %>or virtual instruction exception<% end %> - * `1`: The instruction is executed - - To summarize access: - [separator="!",%autowidth] - !=== - ! `menvcfg.CBCFE` ! `senvcfg.CBCFE` behavior - - ! 0 ! read-only 0 - ! 1 - a! writeable, independent bit from `menvcfg.CBCFE` - !=== - - See `cbo.clean` and/or `cbo.flush` for a summary of the effect. - - definedBy: Zicbom - type: RW - reset_value: UNDEFINED_LEGAL - CBIE: - location: 5-4 - description: | - *Cache Block Invalidate instruction Enable* - - This field has restricted values based on the value of `menvcfg.CBIE`. - When an invalid value is written, it is ignored and the field remains unchanged. - - [separator="!",%autowidth,cols=",.>"] - !=== - ! [.rotate]#`menvcfg.CBIE`# ! Valid values of `senvcfg.CBIE` - - ! 00 ! 00 - ! 01 ! 00, 01 - ! 11 ! 00, 01, 11 - !=== - - Controls execution of the cache block invalidate instruction, `cbo.inval`, - in U-mode - <% if ext?(:H) %> - and VU-mode (together with `henvcfg.CBIE`) - <% end %> - . - - * `00`: The instruction raises an illegal instruction or virtual instruction exception - * `01`: The instruction is executed and performs a flush operation - * `10`: _Reserved_ - * `11`: The instruction is executed and performs an invalidate operation - - See `cbo.inval` for more details. - definedBy: Zicbom - type: RW-R - sw_write(csr_value): | - if (csr_value.CBIE == 0 || csr_value.CBIE == 1 || csr_value.CBIE == 3) { - return csr_value.CBIE; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } - reset_value: UNDEFINED_LEGAL - FIOM: - location: 0 - description: | - *Fence of I/O implies Memory* - - When either `senvcfg.FIOM` or `menvcfg.FIOM` is set, - FENCE instructions ordering I/O regions also implicitly order memory regions when executed - in U-mode as follows: - - [separator="!",%autowidth,float="center",align="center",cols="^,<",options="header"] - !=== - !Instruction bit !Meaning when set - !PI + - PO - !Predecessor device input and memory reads (PR implied) + - Predecessor device output and memory writes (PW implied) - !SI + - SO - !Successor device input and memory reads (SR implied) + - Successor device output and memory writes (SW implied) - !=== - - Similarly, in U-mode when FIOM=1, if an atomic - instruction that accesses a region ordered as device I/O has its _aq_ - and/or _rl_ bit set, then that instruction is ordered as though it - accesses both device I/O and memory. - - See `fence` for more details. - - type: RW - reset_value: 0 \ No newline at end of file +$schema: "csr_schema.json#" +kind: csr +name: senvcfg +address: 0x10A +long_name: Supervisor Environment Configuration +description: Contains bits to enable/disable extensions +priv_mode: S +length: 64 +definedBy: + allOf: + - name: Sm + version: ">=1.12" + - name: S +fields: + CBZE: + location: 7 + description: | + *Cache Block Zero instruction Enable* + + Bit is read-only 0 when `menvcfg.CBZE` is clear. + + Enables the execution of the cache block zero instruction, `cbo.zero`, + in U-mode<% if ext?(:H) %> and (in conjunction with `henvcfg.CBZE`) VU-mode<% end %>. + + * `0`: The instruction raises an illegal instruction<% if ext?(:H) %> or virtual instruction exception<% end %> + * `1`: The instruction is executed + + To summarize access: + [separator="!",%autowidth] + !=== + ! `menvcfg.CBZE` ! `senvcfg.CBZE` behavior + + ! 0 ! read-only 0 + ! 1 + a! writeable, independent bit from `menvcfg.CBZE` + !=== + + See `cbo.zero` for a summary of the effect. + + definedBy: Zicboz + type: RW + reset_value: UNDEFINED_LEGAL + CBCFE: + location: 6 + description: | + *Cache Block Clean and Flush instruction Enable* + + Enables the execution of the cache block clean instruction, `cbo.clean`, and the + cache block flush instruction, `cbo.flush`, + <% if ext?(:S) %> + in S-mode + <% elsif ext?(:U) %> + in U-mode + <% end %>. + + * `0`: The instruction raises an illegal instruction <% if ext?(:H) %>or virtual instruction exception<% end %> + * `1`: The instruction is executed + + To summarize access: + [separator="!",%autowidth] + !=== + ! `menvcfg.CBCFE` ! `senvcfg.CBCFE` behavior + + ! 0 ! read-only 0 + ! 1 + a! writeable, independent bit from `menvcfg.CBCFE` + !=== + + See `cbo.clean` and/or `cbo.flush` for a summary of the effect. + + definedBy: Zicbom + type: RW + reset_value: UNDEFINED_LEGAL + CBIE: + location: 5-4 + description: | + *Cache Block Invalidate instruction Enable* + + This field has restricted values based on the value of `menvcfg.CBIE`. + When an invalid value is written, it is ignored and the field remains unchanged. + + [separator="!",%autowidth,cols=",.>"] + !=== + ! [.rotate]#`menvcfg.CBIE`# ! Valid values of `senvcfg.CBIE` + + ! 00 ! 00 + ! 01 ! 00, 01 + ! 11 ! 00, 01, 11 + !=== + + Controls execution of the cache block invalidate instruction, `cbo.inval`, + in U-mode + <% if ext?(:H) %> + and VU-mode (together with `henvcfg.CBIE`) + <% end %> + . + + * `00`: The instruction raises an illegal instruction or virtual instruction exception + * `01`: The instruction is executed and performs a flush operation + * `10`: _Reserved_ + * `11`: The instruction is executed and performs an invalidate operation + + See `cbo.inval` for more details. + definedBy: Zicbom + type: RW-R + sw_write(csr_value): | + if (csr_value.CBIE == 0 || csr_value.CBIE == 1 || csr_value.CBIE == 3) { + return csr_value.CBIE; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } + reset_value: UNDEFINED_LEGAL + FIOM: + location: 0 + description: | + *Fence of I/O implies Memory* + + When either `senvcfg.FIOM` or `menvcfg.FIOM` is set, + FENCE instructions ordering I/O regions also implicitly order memory regions when executed + in U-mode as follows: + + [separator="!",%autowidth,float="center",align="center",cols="^,<",options="header"] + !=== + !Instruction bit !Meaning when set + !PI + + PO + !Predecessor device input and memory reads (PR implied) + + Predecessor device output and memory writes (PW implied) + !SI + + SO + !Successor device input and memory reads (SR implied) + + Successor device output and memory writes (SW implied) + !=== + + Similarly, in U-mode when FIOM=1, if an atomic + instruction that accesses a region ordered as device I/O has its _aq_ + and/or _rl_ bit set, then that instruction is ordered as though it + accesses both device I/O and memory. + + See `fence` for more details. + + type: RW + reset_value: 0 \ No newline at end of file diff --git a/arch/csr/sepc.yaml b/arch/csr/sepc.yaml index 0e2005e48..4cc4b9de7 100644 --- a/arch/csr/sepc.yaml +++ b/arch/csr/sepc.yaml @@ -1,43 +1,45 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -sepc: - long_name: Supervisor Exception Program Counter - address: 0x141 - priv_mode: S - length: 64 - description: | - Written with the PC of an instruction on an exception or interrupt taken in (H)S-mode. +$schema: "csr_schema.json#" +kind: csr +name: sepc +long_name: Supervisor Exception Program Counter +address: 0x141 +priv_mode: S +length: 64 +description: | + Written with the PC of an instruction on an exception or interrupt taken in (H)S-mode. - Also controls where the hart jumps on an exception return from (H)S-mode. - definedBy: S - fields: - PC: - location: 63-0 - description: | - When a trap is taken into S-mode, `sepc.PC` is written with the virtual address of the - instruction that was interrupted or that encountered the exception. - Otherwise, `sepc.PC` is never written by the implementation, though it may be explicitly written - by software. + Also controls where the hart jumps on an exception return from (H)S-mode. +definedBy: S +fields: + PC: + location: 63-0 + description: | + When a trap is taken into S-mode, `sepc.PC` is written with the virtual address of the + instruction that was interrupted or that encountered the exception. + Otherwise, `sepc.PC` is never written by the implementation, though it may be explicitly written + by software. - On an exception retun from S-mode (from the SRET instruction), - control transfers to the virtual address read out of `sepc.PC`. + On an exception retun from S-mode (from the SRET instruction), + control transfers to the virtual address read out of `sepc.PC`. - Because PCs are always <% if ext?(:C) %>halfword<% else %>word<% end %>-aligned, - <% if ext?(:C) %>bit 0<% else %>bits 1:0<% end %> of `sepc.PC` are always - read-only 0. + Because PCs are always <% if ext?(:C) %>halfword<% else %>word<% end %>-aligned, + <% if ext?(:C) %>bit 0<% else %>bits 1:0<% end %> of `sepc.PC` are always + read-only 0. - [when,"ext?(:C) && MUTABLE_MISA_C == true"] - When `misa.C` is clear, bit 1 is masked to zero. Writes to bit 1 are still captured, and - may be visible on the next read with `misa.C` is set. + [when,"ext?(:C) && MUTABLE_MISA_C == true"] + When `misa.C` is clear, bit 1 is masked to zero. Writes to bit 1 are still captured, and + may be visible on the next read with `misa.C` is set. - Holds bits 63:<%= ext?(:C) ? 2 : 1 %> of the virtual address associated with an exception. - type: RW-RH - sw_write(csr_value): | - return csr_value.PC & ~64'b1; - reset_value: UNDEFINED_LEGAL - sw_read(): | - if (implemented?(ExtensionName::C) && CSR[misa].C == 1'b1) { - return CSR[sepc].PC & ~64'b1; - } else { - return CSR[sepc].PC; - } + Holds bits 63:<%= ext?(:C) ? 2 : 1 %> of the virtual address associated with an exception. + type: RW-RH + sw_write(csr_value): | + return csr_value.PC & ~64'b1; + reset_value: UNDEFINED_LEGAL +sw_read(): | + if (implemented?(ExtensionName::C) && CSR[misa].C == 1'b1) { + return CSR[sepc].PC & ~64'b1; + } else { + return CSR[sepc].PC; + } diff --git a/arch/csr/sip.yaml b/arch/csr/sip.yaml index 49487cba9..6de22310d 100644 --- a/arch/csr/sip.yaml +++ b/arch/csr/sip.yaml @@ -1,144 +1,146 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -sip: - long_name: Supervisor Interrupt Pending - address: 0x144 - priv_mode: S - description: | - A restricted view of the interrupt pending bits in `mip`. - - Hypervisor-related interrupts (VS-mode interrupts and Supervisor Guest interrupts) are not reflected - in `sip` even though those interrupts can be taken in HS-mode. Instead, they are reported through `hip`. - length: 64 - definedBy: S - fields: - SSIP: - location: 1 - alias: - - sip.SSIP - - mvip.SSIP - description: | - *Supervisor Software Interrupt Pending* - - Reports the current pending state of an (H)S-mode software interrupt. - - When Supervisor Software Interrupts are not delegated to (H)S-mode (`mideleg.SSI` is clear), `sip.SSIP` is read-only 0. - - Otherwise, `sip.SSIP` is an alias of `mip.SSIP`. - - <%- if ext?(:Smaia) -%> - When using AIA/IMSIC, IPIs are expected to be delivered as external interrupts - and SSIP is not backed by any hardware update (aside from any aliasing effects). - - However, SSIP is still writable by S-mode software and, when written, can be used to - generate an S-mode Software Interrupt. - <%- end -%> - - Since it is an alias, writes to `sip.SSIP` are also be reflected in `mip.SSIP`<% if ext?(:Smaia) %> and `mvip.SSIP`<% end %>. - - <% if ext?(:Smaia) %>_Aliases_<% else %>_Alias_<% end %>: - - * `mip.SSIP` when `mideleg.SSI` is set - <%- if ext?(:Smaia) -%> - * `mvip.SSIP` when `mideleg.SSI` is set - <%- end -%> - - To summarize: - [separator="!",%autowidth] - !=== - ! `mideleg.SSI` ! `sip.SSIP` behavior - - ! 0 ! read-only 0 - ! 1 ! writeable alias of `mip.SSIP` <% if ext?(:Smaia) %>and `mvip.SSIP`<% end %> - !=== - type: RW - reset_value: UNDEFINED_LEGAL - definedBy: S - affectedBy: Smaia - STIP: - location: 5 - alias: - - mip.STIP - - mvip.STIP - description: | - *Supervisor Timer Interrupt Pending* - - Reports the current pending state of an (H)S-mode timer interrupt. - - When Supervisor Timer Interrupts are not delegated to (H)S-mode (_i.e._, `mideleg.STI` is clear), `sip.STIP` is read-only 0. - - Otherwise, `sip.STIP` is a read-only view of `mip.STIP`. - - <% if ext?(:Smaia) %>_Aliases_<% else %>_Alias_<% end %>: - - * `mip.STIP` when `mideleg.STI` is set - <%- if ext?(:Smaia) -%> - * `mvip.STIP` when `mideleg.SSI` is set and `menvcfg.STCE` is clear. - <%- end -%> - - To summarize: - [separator="!",%autowidth] - !=== - ! `mideleg.STI` ! `sip.STIP` behavior - - ! 0 ! read-only 0 - ! 1 ! read-only alias of `mip.STIP` <% if ext?(:Smaia) %>(and `mvip.STIP` when `menvcfg.STCE` is clear)<% end %> - !=== - type: RO-H - reset_value: UNDEFINED_LEGAL - definedBy: S - affectedBy: Sstc - SEIP: - location: 9 - alias: - - mip.SEIP - description: | - *Supervisor External Interrupt Pending* - - Reports the current pending state of an (H)S-mode external interrupt. - - When Supervisor External Interrupts are not delegated to (H)S-mode (_i.e._, `mideleg.SEI` is clear), `sip.SEIP` is read-only 0. - - Otherwise, `sip.SEIP` is a read-only view of `mip.SEIP`. - - To summarize: - [separator="!",%autowidth] - !=== - ! `mideleg.SEI` ! `sip.SEIP` behavior - - ! 0 ! read-only 0 - ! 1 ! read-only alias of `mip.SEIP` - !=== - - type: RO-H - definedBy: S - affectedBy: Smaia - reset_value: UNDEFINED_LEGAL - LCOFIP: - location: 13 - alias: - - mip.LCOFIP - - vsip.LCOFIP - description: | - *Local Counter Overflow Interrupt pending* - - Reports the current pending state of a Local Counter Overflow interrupt. - - When Local Counter Overflow interrupts are not delegated to (H)S-mode (_i.e._, `mideleg.LCOFI` is clear), `sip.LCOFIP` is read-only 0. - - Otherwise, `sip.LCOFIP` is an alias of `mip.LCOFIP`. - - Software writes 0 to `sip.LCOFIP` to clear the pending interrupt. - - To summarize: - [separator="!",%autowidth] - !=== - ! `mideleg.LCOFI` ! `sip.LCOFIP` behavior - - ! 0 ! read-only 0 - ! 1 - a! writeable alias of `mip.LCOFIP` (and `vsip.LCOFIP` when `hideleg.LCOFI` is set) - !=== - type: RW-H - reset_value: UNDEFINED_LEGAL - definedBy: Sscofpmf +$schema: "csr_schema.json#" +kind: csr +name: sip +long_name: Supervisor Interrupt Pending +address: 0x144 +priv_mode: S +description: | + A restricted view of the interrupt pending bits in `mip`. + + Hypervisor-related interrupts (VS-mode interrupts and Supervisor Guest interrupts) are not reflected + in `sip` even though those interrupts can be taken in HS-mode. Instead, they are reported through `hip`. +length: 64 +definedBy: S +fields: + SSIP: + location: 1 + alias: + - sip.SSIP + - mvip.SSIP + description: | + *Supervisor Software Interrupt Pending* + + Reports the current pending state of an (H)S-mode software interrupt. + + When Supervisor Software Interrupts are not delegated to (H)S-mode (`mideleg.SSI` is clear), `sip.SSIP` is read-only 0. + + Otherwise, `sip.SSIP` is an alias of `mip.SSIP`. + + <%- if ext?(:Smaia) -%> + When using AIA/IMSIC, IPIs are expected to be delivered as external interrupts + and SSIP is not backed by any hardware update (aside from any aliasing effects). + + However, SSIP is still writable by S-mode software and, when written, can be used to + generate an S-mode Software Interrupt. + <%- end -%> + + Since it is an alias, writes to `sip.SSIP` are also be reflected in `mip.SSIP`<% if ext?(:Smaia) %> and `mvip.SSIP`<% end %>. + + <% if ext?(:Smaia) %>_Aliases_<% else %>_Alias_<% end %>: + + * `mip.SSIP` when `mideleg.SSI` is set + <%- if ext?(:Smaia) -%> + * `mvip.SSIP` when `mideleg.SSI` is set + <%- end -%> + + To summarize: + [separator="!",%autowidth] + !=== + ! `mideleg.SSI` ! `sip.SSIP` behavior + + ! 0 ! read-only 0 + ! 1 ! writeable alias of `mip.SSIP` <% if ext?(:Smaia) %>and `mvip.SSIP`<% end %> + !=== + type: RW + reset_value: UNDEFINED_LEGAL + definedBy: S + affectedBy: Smaia + STIP: + location: 5 + alias: + - mip.STIP + - mvip.STIP + description: | + *Supervisor Timer Interrupt Pending* + + Reports the current pending state of an (H)S-mode timer interrupt. + + When Supervisor Timer Interrupts are not delegated to (H)S-mode (_i.e._, `mideleg.STI` is clear), `sip.STIP` is read-only 0. + + Otherwise, `sip.STIP` is a read-only view of `mip.STIP`. + + <% if ext?(:Smaia) %>_Aliases_<% else %>_Alias_<% end %>: + + * `mip.STIP` when `mideleg.STI` is set + <%- if ext?(:Smaia) -%> + * `mvip.STIP` when `mideleg.SSI` is set and `menvcfg.STCE` is clear. + <%- end -%> + + To summarize: + [separator="!",%autowidth] + !=== + ! `mideleg.STI` ! `sip.STIP` behavior + + ! 0 ! read-only 0 + ! 1 ! read-only alias of `mip.STIP` <% if ext?(:Smaia) %>(and `mvip.STIP` when `menvcfg.STCE` is clear)<% end %> + !=== + type: RO-H + reset_value: UNDEFINED_LEGAL + definedBy: S + affectedBy: Sstc + SEIP: + location: 9 + alias: + - mip.SEIP + description: | + *Supervisor External Interrupt Pending* + + Reports the current pending state of an (H)S-mode external interrupt. + + When Supervisor External Interrupts are not delegated to (H)S-mode (_i.e._, `mideleg.SEI` is clear), `sip.SEIP` is read-only 0. + + Otherwise, `sip.SEIP` is a read-only view of `mip.SEIP`. + + To summarize: + [separator="!",%autowidth] + !=== + ! `mideleg.SEI` ! `sip.SEIP` behavior + + ! 0 ! read-only 0 + ! 1 ! read-only alias of `mip.SEIP` + !=== + + type: RO-H + definedBy: S + affectedBy: Smaia + reset_value: UNDEFINED_LEGAL + LCOFIP: + location: 13 + alias: + - mip.LCOFIP + - vsip.LCOFIP + description: | + *Local Counter Overflow Interrupt pending* + + Reports the current pending state of a Local Counter Overflow interrupt. + + When Local Counter Overflow interrupts are not delegated to (H)S-mode (_i.e._, `mideleg.LCOFI` is clear), `sip.LCOFIP` is read-only 0. + + Otherwise, `sip.LCOFIP` is an alias of `mip.LCOFIP`. + + Software writes 0 to `sip.LCOFIP` to clear the pending interrupt. + + To summarize: + [separator="!",%autowidth] + !=== + ! `mideleg.LCOFI` ! `sip.LCOFIP` behavior + + ! 0 ! read-only 0 + ! 1 + a! writeable alias of `mip.LCOFIP` (and `vsip.LCOFIP` when `hideleg.LCOFI` is set) + !=== + type: RW-H + reset_value: UNDEFINED_LEGAL + definedBy: Sscofpmf diff --git a/arch/csr/sscratch.yaml b/arch/csr/sscratch.yaml index 81069c2ac..dceaf1486 100644 --- a/arch/csr/sscratch.yaml +++ b/arch/csr/sscratch.yaml @@ -1,15 +1,17 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -sscratch: - long_name: Supervisor Scratch Register - address: 0x140 - priv_mode: S - length: 64 - description: Scratch register for software use. Bits are not interpreted by hardware. - definedBy: S # actually, defined by RV64, but must implement U-mode for this CSR to exist - fields: - SCRATCH: - location: 63-0 - description: Scratch value - type: RW - reset_value: UNDEFINED_LEGAL +$schema: "csr_schema.json#" +kind: csr +name: sscratch +long_name: Supervisor Scratch Register +address: 0x140 +priv_mode: S +length: 64 +description: Scratch register for software use. Bits are not interpreted by hardware. +definedBy: S # actually, defined by RV64, but must implement U-mode for this CSR to exist +fields: + SCRATCH: + location: 63-0 + description: Scratch value + type: RW + reset_value: UNDEFINED_LEGAL diff --git a/arch/csr/sstatus.yaml b/arch/csr/sstatus.yaml index 8a124435b..ba014122e 100644 --- a/arch/csr/sstatus.yaml +++ b/arch/csr/sstatus.yaml @@ -1,130 +1,132 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -sstatus: - long_name: Supervisor Status - address: 0x100 - priv_mode: S - length: SXLEN - description: | - The sstatus register tracks and controls the hart's current operating state. +$schema: "csr_schema.json#" +kind: csr +name: sstatus +long_name: Supervisor Status +address: 0x100 +priv_mode: S +length: SXLEN +description: | + The sstatus register tracks and controls the hart's current operating state. - All fields in sstatus are aliases of the same field in mstatus. - definedBy: S - fields: - SD: - # The *position* of SD changes when SXLEN changes (yuck^[TM]) - location_rv32: 31 - location_rv64: 63 - alias: mstatus.SD - description: | - *State Dirty* + All fields in sstatus are aliases of the same field in mstatus. +definedBy: S +fields: + SD: + # The *position* of SD changes when SXLEN changes (yuck^[TM]) + location_rv32: 31 + location_rv64: 63 + alias: mstatus.SD + description: | + *State Dirty* - Alias of `mstatus.SD`. - - type: RO-H - reset_value: UNDEFINED_LEGAL - affectedBy: [F, D, V] - UXL: - location: 33-32 - base: 64 - alias: mstatus.MXR - description: | - *U-mode XLEN* + Alias of `mstatus.SD`. + + type: RO-H + reset_value: UNDEFINED_LEGAL + affectedBy: [F, D, V] + UXL: + location: 33-32 + base: 64 + alias: mstatus.MXR + description: | + *U-mode XLEN* - Alias of `mstatus.UXL`. - - type: RO - reset_value: UNDEFINED_LEGAL - MXR: - alias: mstatus.MXR - location: 19 - description: | - *Make eXecutable Readable* + Alias of `mstatus.UXL`. + + type: RO + reset_value: UNDEFINED_LEGAL + MXR: + alias: mstatus.MXR + location: 19 + description: | + *Make eXecutable Readable* - Alias of `mstatus.MXR`. - - type: RW - reset_value: UNDEFINED_LEGAL - SUM: - alias: mstatus.SUM - location: 18 - description: | - *permit Supervisor Memory Access* + Alias of `mstatus.MXR`. + + type: RW + reset_value: UNDEFINED_LEGAL + SUM: + alias: mstatus.SUM + location: 18 + description: | + *permit Supervisor Memory Access* - Alias of `mstatus.SUM`. - - type: RW - reset_value: UNDEFINED_LEGAL - XS: - alias: mstatus.XS - location: 16-15 - description: | - Custom (X) extension context Status. - - Alias of `mstatus.XS`. - - type: RO - reset_value: UNDEFINED_LEGAL - FS: - alias: mstatus.FS - location: 14-13 - description: | - Floating point context status. + Alias of `mstatus.SUM`. + + type: RW + reset_value: UNDEFINED_LEGAL + XS: + alias: mstatus.XS + location: 16-15 + description: | + Custom (X) extension context Status. + + Alias of `mstatus.XS`. + + type: RO + reset_value: UNDEFINED_LEGAL + FS: + alias: mstatus.FS + location: 14-13 + description: | + Floating point context status. - Alias of `mstatus.FS`. + Alias of `mstatus.FS`. - type: RW-H - definedBy: F - reset_value: UNDEFINED_LEGAL - VS: - alias: mstatus.VS - location: 10-9 - description: | - Vector context status. + type: RW-H + definedBy: F + reset_value: UNDEFINED_LEGAL + VS: + alias: mstatus.VS + location: 10-9 + description: | + Vector context status. - Alias of `mstatus.VS`. + Alias of `mstatus.VS`. - type: RW-H - reset_value: UNDEFINED_LEGAL - definedBy: V - SPP: - alias: mstatus.SPP - location: 8 - description: | - *S-mode Previous Privilege* + type: RW-H + reset_value: UNDEFINED_LEGAL + definedBy: V + SPP: + alias: mstatus.SPP + location: 8 + description: | + *S-mode Previous Privilege* - Alias of `mstatus.SPP`. - type: RW-H - definedBy: S - reset_value: UNDEFINED_LEGAL - UBE: - alias: mstatus.UBE - location: 6 - description: | - *U-mode Big Endian* + Alias of `mstatus.SPP`. + type: RW-H + definedBy: S + reset_value: UNDEFINED_LEGAL + UBE: + alias: mstatus.UBE + location: 6 + description: | + *U-mode Big Endian* - Alias of `mstatus.UBE`. - type: RO - definedBy: S - reset_value: UNDEFINED_LEGAL - SPIE: - alias: mstatus.SPIE - location: 5 - description: | - *S-mode Previous Interrupt Enable* + Alias of `mstatus.UBE`. + type: RO + definedBy: S + reset_value: UNDEFINED_LEGAL + SPIE: + alias: mstatus.SPIE + location: 5 + description: | + *S-mode Previous Interrupt Enable* - Alias of `mstatus.SPIE`. - - type: RW-H - definedBy: S - reset_value: UNDEFINED_LEGAL - SIE: - alias: mstatus.SIE - location: 1 - description: | - *S-mode Interrupt Enable* + Alias of `mstatus.SPIE`. + + type: RW-H + definedBy: S + reset_value: UNDEFINED_LEGAL + SIE: + alias: mstatus.SIE + location: 1 + description: | + *S-mode Interrupt Enable* - Alias of `mstatus.SIE`. - - type: RW-H - reset_value: UNDEFINED_LEGAL \ No newline at end of file + Alias of `mstatus.SIE`. + + type: RW-H + reset_value: UNDEFINED_LEGAL \ No newline at end of file diff --git a/arch/csr/stval.yaml b/arch/csr/stval.yaml index 08d741b95..0e2a64bf4 100644 --- a/arch/csr/stval.yaml +++ b/arch/csr/stval.yaml @@ -1,95 +1,97 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -stval: - long_name: Supervisor Trap Value - address: 0x143 - description: Holds trap-specific information - priv_mode: S - length: 64 - definedBy: S - fields: - VALUE: - location: 63-0 - description: | - Written with trap-specific information when a trap is taken into S-mode. +$schema: "csr_schema.json#" +kind: csr +name: stval +long_name: Supervisor Trap Value +address: 0x143 +description: Holds trap-specific information +priv_mode: S +length: 64 +definedBy: S +fields: + VALUE: + location: 63-0 + description: | + Written with trap-specific information when a trap is taken into S-mode. - The values are: + The values are: - [separator="!"] - !=== - ! Exception type ! Value + [separator="!"] + !=== + ! Exception type ! Value - ! [0] Instruction address misaligned ! The misaligned virtual PC (same as the value written to `mepc`). - ! [1] Instruction access fault ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the access fault <%- unless ext?(:C) -%>(same as the value written to `mepc`)<%- end -%>. - ! [2] Illegal Instruction ! The encoding of the illegal instruction. - ! [3] Breakpoint - ! [when,"REPORT_VA_IN_STVAL_ON_BREAKPOINT == true"] - When caused by an EBREAK instruction, the virtual PC of the breakpoint instruction. - - [when,"REPORT_VA_IN_STVAL_ON_BREAKPOINT == false"] - When caused by an EBREAK instruction, zero. + ! [0] Instruction address misaligned ! The misaligned virtual PC (same as the value written to `mepc`). + ! [1] Instruction access fault ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the access fault <%- unless ext?(:C) -%>(same as the value written to `mepc`)<%- end -%>. + ! [2] Illegal Instruction ! The encoding of the illegal instruction. + ! [3] Breakpoint + ! [when,"REPORT_VA_IN_STVAL_ON_BREAKPOINT == true"] + When caused by an EBREAK instruction, the virtual PC of the breakpoint instruction. + + [when,"REPORT_VA_IN_STVAL_ON_BREAKPOINT == false"] + When caused by an EBREAK instruction, zero. - When caused by a data address (_i.e._, watchpoint) breakpoint, the faulting virtual address. - When caused by an instruction address breakpoint, the faulting virtual PC. - ! [4] Load address misaligned ! The misaligned virtual load address. - ! [5] Load access fault - ! The part of virtual load address causing in the access fault. + When caused by a data address (_i.e._, watchpoint) breakpoint, the faulting virtual address. + When caused by an instruction address breakpoint, the faulting virtual PC. + ! [4] Load address misaligned ! The misaligned virtual load address. + ! [5] Load access fault + ! The part of virtual load address causing in the access fault. - When the load is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, - address + 4 is reported). + When the load is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, + address + 4 is reported). - (Even though the access fault arises on a physical address, the virtual address is reported) - ! [6] Store/AMO address misaligned ! The misaligned virtual store/AMO address. - ! [7] Store/AMO access fault - ! The virtual store/AMO address causing the access fault. - - When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, - address + 4 is reported). + (Even though the access fault arises on a physical address, the virtual address is reported) + ! [6] Store/AMO address misaligned ! The misaligned virtual store/AMO address. + ! [7] Store/AMO access fault + ! The virtual store/AMO address causing the access fault. + + When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, + address + 4 is reported). - (Even though the access fault arises on a physical address, the virtual address is reported) - ! [8] Environment call from U-mode <% if ext?(:H) %>or VU-mode<% end %> ! Zero - ! [9] Environment call from (H)S-mode ! Zero - <%- if ext?(:H) -%> - ! [10] Environment call from VS-mode ! Zero - <%- end -%> - ! [12] Instruction page fault - ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the page fault - <% unless ext?(:C) %>(same as the value written to `mepc`)<% end %>. - ! [13] Load page fault - ! The part of the virtual load address causing in the page fault. - - When the load is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, address + 4 is reported). - ! [15] Store/AMO page fault - ! The virtual store/AMO address causing in the page fault. - - When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, address + 4 is reported). - <%- if ext?(:H) -%> - ! [20] Instruction guest-page fault - ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the fault <% unless ext?(:C) %>(same as the value written to `mepc`)<% end %>. + (Even though the access fault arises on a physical address, the virtual address is reported) + ! [8] Environment call from U-mode <% if ext?(:H) %>or VU-mode<% end %> ! Zero + ! [9] Environment call from (H)S-mode ! Zero + <%- if ext?(:H) -%> + ! [10] Environment call from VS-mode ! Zero + <%- end -%> + ! [12] Instruction page fault + ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the page fault + <% unless ext?(:C) %>(same as the value written to `mepc`)<% end %>. + ! [13] Load page fault + ! The part of the virtual load address causing in the page fault. - The guest physical address is reported in `mtval2`. - ! [21] Load guest-page fault - ! The part of the virtual address causing the fault. + When the load is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, address + 4 is reported). + ! [15] Store/AMO page fault + ! The virtual store/AMO address causing in the page fault. + + When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, address + 4 is reported). + <%- if ext?(:H) -%> + ! [20] Instruction guest-page fault + ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the fault <% unless ext?(:C) %>(same as the value written to `mepc`)<% end %>. + + The guest physical address is reported in `mtval2`. + ! [21] Load guest-page fault + ! The part of the virtual address causing the fault. - When the load is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, address + 4 is reported). - - The guest physical address is reported in `mtval2`. - ! [22] Virutal instruction - ! The encoding of the faulting virtual instruction. - ! [23] Store/AMO guest-page fault - ! The part of the virtual address causing the fault. + When the load is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, address + 4 is reported). + + The guest physical address is reported in `mtval2`. + ! [22] Virutal instruction + ! The encoding of the faulting virtual instruction. + ! [23] Store/AMO guest-page fault + ! The part of the virtual address causing the fault. + + When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, address + 4 is reported). - When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, address + 4 is reported). - - The guest physical address is reported in `htval`. - <%- end -%> - !=== + The guest physical address is reported in `htval`. + <%- end -%> + !=== - type: RW-H - reset_value: 0 + type: RW-H + reset_value: 0 diff --git a/arch/csr/stvec.yaml b/arch/csr/stvec.yaml index f0d038508..acc02efed 100644 --- a/arch/csr/stvec.yaml +++ b/arch/csr/stvec.yaml @@ -1,46 +1,48 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -stvec: - long_name: Supervisor Trap Vector - address: 0x105 - priv_mode: S - length: 64 - description: Controls where traps jump. - definedBy: S - fields: - BASE: - location: 63-2 - description: | - <%- va_size = ext?(:Sv57) ? 57 : (ext?(:Sv48) ? 49 :39) -%> - Bit 63:0 of the virtual address of the exception vector for any trap taken into S-mode. +$schema: "csr_schema.json#" +kind: csr +name: stvec +long_name: Supervisor Trap Vector +address: 0x105 +priv_mode: S +length: 64 +description: Controls where traps jump. +definedBy: S +fields: + BASE: + location: 63-2 + description: | + <%- va_size = ext?(:Sv57) ? 57 : (ext?(:Sv48) ? 49 :39) -%> + Bit 63:0 of the virtual address of the exception vector for any trap taken into S-mode. - If the base address is written with a non-cannonical address (_i.e._, bits 63:<%= va_size %> do not match bit <%= va_size-1 %>), - the write should be ignored. + If the base address is written with a non-cannonical address (_i.e._, bits 63:<%= va_size %> do not match bit <%= va_size-1 %>), + the write should be ignored. - type: RW-R - sw_write(csr_value): | - # Base spec says that BASE must be 4-byte aligned, which will always be the case - # implementations may put further constraints on BASE when MODE != Direct - # If that is the case, stvec should have an override for the implementation - return csr_value.BASE; - reset_value: UNDEFINED_LEGAL - MODE: - location: 1-0 - description: | - Vectoring mode for asynchronous interrupts. - - 0 - Direct, 1 - Vectored + type: RW-R + sw_write(csr_value): | + # Base spec says that BASE must be 4-byte aligned, which will always be the case + # implementations may put further constraints on BASE when MODE != Direct + # If that is the case, stvec should have an override for the implementation + return csr_value.BASE; + reset_value: UNDEFINED_LEGAL + MODE: + location: 1-0 + description: | + Vectoring mode for asynchronous interrupts. + + 0 - Direct, 1 - Vectored - When Direct, all synchronous exceptions and asynchronous interrupts jump to (`stvec.BASE` << 2). + When Direct, all synchronous exceptions and asynchronous interrupts jump to (`stvec.BASE` << 2). - When Vectored, asynchronous interrupts jump to (`stvec.BASE` << 2 + `scause.CAUSE`*4) while synchronous exceptions continue to jump to (`stvec.BASE` << 2). - type: RW-R - sw_write(csr_value): | - if (STVEC_MODE_DIRECT && csr_value.MODE == 0) { - return 0; - } else if (STVEC_MODE_VECTORED && csr_value.MODE == 1) { - return 1; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } - reset_value: 0 + When Vectored, asynchronous interrupts jump to (`stvec.BASE` << 2 + `scause.CAUSE`*4) while synchronous exceptions continue to jump to (`stvec.BASE` << 2). + type: RW-R + sw_write(csr_value): | + if (STVEC_MODE_DIRECT && csr_value.MODE == 0) { + return 0; + } else if (STVEC_MODE_VECTORED && csr_value.MODE == 1) { + return 1; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } + reset_value: 0 diff --git a/arch/csr/time.yaml b/arch/csr/time.yaml index 7c31dc485..c900402d9 100644 --- a/arch/csr/time.yaml +++ b/arch/csr/time.yaml @@ -1,81 +1,83 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -time: - long_name: Timer for RDTIME Instruction - address: 0xC01 - description: | - [when,"TIME_CSR_IMPLEMENTED == false"] - This CSR does not exist, and access will cause an IllegalInstruction exception. +$schema: "csr_schema.json#" +kind: csr +name: time +long_name: Timer for RDTIME Instruction +address: 0xC01 +description: | + [when,"TIME_CSR_IMPLEMENTED == false"] + This CSR does not exist, and access will cause an IllegalInstruction exception. - [when,"TIME_CSR_IMPLEMENTED == true"] - -- - Shadow of the memory-mapped M-mode CSR `mtime`. + [when,"TIME_CSR_IMPLEMENTED == true"] + -- + Shadow of the memory-mapped M-mode CSR `mtime`. - Privilege mode access is controlled with `mcounteren.TM`, `scounteren.TM`, and `hcounteren.TM` as follows: + Privilege mode access is controlled with `mcounteren.TM`, `scounteren.TM`, and `hcounteren.TM` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.TM`# .2+h! [.rotate]#`scounteren.TM`# .2+h! [.rotate]#`scounteren.TM`# - 4+^.>h! `time` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.TM`# .2+h! [.rotate]#`scounteren.TM`# .2+h! [.rotate]#`scounteren.TM`# + 4+^.>h! `time` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `Illegal Instruction` ! `Illegal Instruction` ! `Illegal Instruction` ! `Illegal Instruction` - ! 1 ! 0 ! 0 ! read-only ! `Illegal Instruction` ! `Illegal Instruction` ! `Illegal Instruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `Illegal Instruction` ! `Illegal Instruction` - ! 1 ! 0 ! 1 ! read-only ! `Illegal Instruction` ! read-only ! `Illegal Instruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - -- - priv_mode: U - length: 64 - definedBy: Zicntr - fields: - COUNT: - location: 63-0 - description: | - Reports the current wall-clock time from the timer device. + ! 0 ! - ! - ! `Illegal Instruction` ! `Illegal Instruction` ! `Illegal Instruction` ! `Illegal Instruction` + ! 1 ! 0 ! 0 ! read-only ! `Illegal Instruction` ! `Illegal Instruction` ! `Illegal Instruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `Illegal Instruction` ! `Illegal Instruction` + ! 1 ! 0 ! 1 ! read-only ! `Illegal Instruction` ! read-only ! `Illegal Instruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + -- +priv_mode: U +length: 64 +definedBy: Zicntr +fields: + COUNT: + location: 63-0 + description: | + Reports the current wall-clock time from the timer device. - Alias of the `mtime` memory-mapped CSR. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - if (!TIME_CSR_IMPLEMENTED) { - unimplemented_csr($encoding); - } + Alias of the `mtime` memory-mapped CSR. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + if (!TIME_CSR_IMPLEMENTED) { + unimplemented_csr($encoding); + } - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].TM == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].TM == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].TM & CSR[scounteren].TM) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].TM == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].TM == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].TM == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].TM & CSR[scounteren].TM) == 1'b0) && (CSR[mcounteren].IR == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].TM == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].TM & CSR[scounteren].TM) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].TM == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].TM == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].TM == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].TM & CSR[scounteren].TM) == 1'b0) && (CSR[mcounteren].IR == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].TM == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_mtime(); + return read_mtime(); diff --git a/arch/csr/timeh.yaml b/arch/csr/timeh.yaml index 8bab1a319..8d9ebf3b1 100644 --- a/arch/csr/timeh.yaml +++ b/arch/csr/timeh.yaml @@ -1,80 +1,82 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -timeh: - long_name: High-half timer for RDTIME Instruction - address: 0xC81 - description: | - [when,"TIME_CSR_IMPLEMENTED == false"] - This CSR does not exist, and access will cause an IllegalInstruction exception. +$schema: "csr_schema.json#" +kind: csr +name: timeh +long_name: High-half timer for RDTIME Instruction +address: 0xC81 +description: | + [when,"TIME_CSR_IMPLEMENTED == false"] + This CSR does not exist, and access will cause an IllegalInstruction exception. - [when,"TIME_CSR_IMPLEMENTED == true"] - -- - Shadow of the memory-mapped M-mode CSR `mtimeh`. + [when,"TIME_CSR_IMPLEMENTED == true"] + -- + Shadow of the memory-mapped M-mode CSR `mtimeh`. - Privilege mode access is controlled with `mcounteren.TM`, `scounteren.TM`, and `hcounteren.TM` as follows: + Privilege mode access is controlled with `mcounteren.TM`, `scounteren.TM`, and `hcounteren.TM` as follows: - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`mcounteren.TM`# .2+h! [.rotate]#`scounteren.TM`# .2+h! [.rotate]#`scounteren.TM`# - 4+^.>h! `time` behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`mcounteren.TM`# .2+h! [.rotate]#`scounteren.TM`# .2+h! [.rotate]#`scounteren.TM`# + 4+^.>h! `time` behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `Illegal Instruction` ! `Illegal Instruction` ! `Illegal Instruction` ! `Illegal Instruction` - ! 1 ! 0 ! 0 ! read-only ! `Illegal Instruction` ! `Illegal Instruction` ! `Illegal Instruction` - ! 1 ! 1 ! 0 ! read-only ! read-only ! `Illegal Instruction` ! `Illegal Instruction` - ! 1 ! 0 ! 1 ! read-only ! `Illegal Instruction` ! read-only ! `Illegal Instruction` - ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only - !=== - -- - priv_mode: U - length: 32 - definedBy: Zicntr - fields: - COUNT: - location: 31-0 - alias: time.COUNT[63:32] - description: | - Reports the most significant 32 bits of the current wall-clock time from the timer device. - type: RO-H - reset_value: UNDEFINED_LEGAL - sw_read(): | - if (!TIME_CSR_IMPLEMENTED) { - unimplemented_csr($encoding); - } + ! 0 ! - ! - ! `Illegal Instruction` ! `Illegal Instruction` ! `Illegal Instruction` ! `Illegal Instruction` + ! 1 ! 0 ! 0 ! read-only ! `Illegal Instruction` ! `Illegal Instruction` ! `Illegal Instruction` + ! 1 ! 1 ! 0 ! read-only ! read-only ! `Illegal Instruction` ! `Illegal Instruction` + ! 1 ! 0 ! 1 ! read-only ! `Illegal Instruction` ! read-only ! `Illegal Instruction` + ! 1 ! 1 ! 1 ! read-only ! read-only ! read-only ! read-only + !=== + -- +priv_mode: U +length: 32 +definedBy: Zicntr +fields: + COUNT: + location: 31-0 + alias: time.COUNT[63:32] + description: | + Reports the most significant 32 bits of the current wall-clock time from the timer device. + type: RO-H + reset_value: UNDEFINED_LEGAL +sw_read(): | + if (!TIME_CSR_IMPLEMENTED) { + unimplemented_csr($encoding); + } - # access is determined by *counteren CSRs - if (mode() == PrivilegeMode::S) { + # access is determined by *counteren CSRs + if (mode() == PrivilegeMode::S) { + # S-mode is present -> + # mcounteren determines access in S-mode + if (CSR[mcounteren].TM == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::U) { + if (CSR[misa].S == 1'b1) { # S-mode is present -> - # mcounteren determines access in S-mode - if (CSR[mcounteren].TM == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { - # S-mode is present -> - # mcounteren and scounteren together determine access in U-mode - if ((CSR[mcounteren].TM & CSR[scounteren].TM) == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (CSR[mcounteren].TM == 1'b0) { - # S-mode is not present -> - # mcounteren determines access in U-mode - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VS) { - # access in VS mode - if (CSR[hcounteren].TM == 1'b0 && CSR[mcounteren] == 1'b1) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].TM == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } else if (mode() == PrivilegeMode::VU) { - # access in VU mode - if (((CSR[hcounteren].TM & CSR[scounteren].TM) == 1'b0) && (CSR[mcounteren].IR == 1'b1)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else if (CSR[mcounteren].TM == 1'b0) { + # mcounteren and scounteren together determine access in U-mode + if ((CSR[mcounteren].TM & CSR[scounteren].TM) == 1'b0) { raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } else if (CSR[mcounteren].TM == 1'b0) { + # S-mode is not present -> + # mcounteren determines access in U-mode + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VS) { + # access in VS mode + if (CSR[hcounteren].TM == 1'b0 && CSR[mcounteren] == 1'b1) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].TM == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } else if (mode() == PrivilegeMode::VU) { + # access in VU mode + if (((CSR[hcounteren].TM & CSR[scounteren].TM) == 1'b0) && (CSR[mcounteren].IR == 1'b1)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else if (CSR[mcounteren].TM == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - return read_mtime()[63:32]; + return read_mtime()[63:32]; diff --git a/arch/csr/vscause.yaml b/arch/csr/vscause.yaml index cdcbdcc81..56c407058 100644 --- a/arch/csr/vscause.yaml +++ b/arch/csr/vscause.yaml @@ -1,89 +1,91 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -vscause: - long_name: Virtual Supervisor Cause - address: 0x242 - virtual_address: 0x142 - priv_mode: VS - length: VSXLEN - description: Reports the cause of the latest exception taken in VS-mode. - definedBy: H - fields: - INT: - location_rv64: 63 - location_rv32: 31 - description: | - Written by hardware when a trap is taken into VS-mode. - - When set, the last exception was caused by an asynchronous Interrupt. +$schema: "csr_schema.json#" +kind: csr +name: vscause +long_name: Virtual Supervisor Cause +address: 0x242 +virtual_address: 0x142 +priv_mode: VS +length: VSXLEN +description: Reports the cause of the latest exception taken in VS-mode. +definedBy: H +fields: + INT: + location_rv64: 63 + location_rv32: 31 + description: | + Written by hardware when a trap is taken into VS-mode. + + When set, the last exception was caused by an asynchronous Interrupt. - `vscause.INT` is writeable. + `vscause.INT` is writeable. - [when,"TRAP_ON_ILLEGAL_WLRL == true"] - If `vscause` is written with an undefined cause (combination of `vscause.INT` and `vscause.CODE`), an `Illegal Instruction` exception occurs. + [when,"TRAP_ON_ILLEGAL_WLRL == true"] + If `vscause` is written with an undefined cause (combination of `vscause.INT` and `vscause.CODE`), an `Illegal Instruction` exception occurs. - [when,"TRAP_ON_ILLEGAL_WLRL == false"] - If `vscause` is written with an undefined cause (combination of `vscause.INT` and `vscause.CODE`), neither `vscause.INT` nor `vscause.CODE` are modified. - type: RW-RH - sw_write(csr_value): | - # the write only holds if the INT/CODE combination is valid - # otherwise, the old value is retained - if (csr_value.INT == 1) { - if (valid_interrupt_code?(csr_value.CODE)) { - return 1; - } - return ILLEGAL_WLRL; - } else { - if (valid_exception_code?(csr_value.CODE)) { - return 1; - } - return ILLEGAL_WLRL; + [when,"TRAP_ON_ILLEGAL_WLRL == false"] + If `vscause` is written with an undefined cause (combination of `vscause.INT` and `vscause.CODE`), neither `vscause.INT` nor `vscause.CODE` are modified. + type: RW-RH + sw_write(csr_value): | + # the write only holds if the INT/CODE combination is valid + # otherwise, the old value is retained + if (csr_value.INT == 1) { + if (valid_interrupt_code?(csr_value.CODE)) { + return 1; } - reset_value: UNDEFINED_LEGAL - CODE: - location_rv32: 30-0 - location_rv64: 62-0 - description: | - Written by hardware when a trap is taken into VS-mode. + return ILLEGAL_WLRL; + } else { + if (valid_exception_code?(csr_value.CODE)) { + return 1; + } + return ILLEGAL_WLRL; + } + reset_value: UNDEFINED_LEGAL + CODE: + location_rv32: 30-0 + location_rv64: 62-0 + description: | + Written by hardware when a trap is taken into VS-mode. - Holds the interrupt or exception code for the last taken trap. + Holds the interrupt or exception code for the last taken trap. - `vscause.CODE` is writeable. + `vscause.CODE` is writeable. - [when,"TRAP_ON_ILLEGAL_WLRL == true"] - If `vscause` is written with an undefined cause (combination of `vscause.INT` and `vscause.CODE`), an `Illegal Instruction` exception occurs. + [when,"TRAP_ON_ILLEGAL_WLRL == true"] + If `vscause` is written with an undefined cause (combination of `vscause.INT` and `vscause.CODE`), an `Illegal Instruction` exception occurs. - [when,"TRAP_ON_ILLEGAL_WLRL == false"] - If `vscause` is written with an undefined cause (combination of `vscause.INT` and `vscause.CODE`), neither `vscause.INT` nor `vscause.CODE` are modified. + [when,"TRAP_ON_ILLEGAL_WLRL == false"] + If `vscause` is written with an undefined cause (combination of `vscause.INT` and `vscause.CODE`), neither `vscause.INT` nor `vscause.CODE` are modified. - Valid interrupt codes are: - [separator="!"] - !=== - <%- interrupt_codes.sort_by { |code| code.num }.each do |code| -%> - ! <%= code.num %> ! <%= code.name %> - <%- end -%> - !=== + Valid interrupt codes are: + [separator="!"] + !=== + <%- interrupt_codes.sort_by { |code| code.num }.each do |code| -%> + ! <%= code.num %> ! <%= code.name %> + <%- end -%> + !=== - Valid exception codes are: - [separator="!"] - !=== - <%- exception_codes.sort_by { |code| code.num }.each do |code| -%> - ! <%= code.num %> ! <%= code.name %> - <%- end -%> - !=== - type: RW-RH - sw_write(csr_value): | - # the write only holds if the INT/CODE combination is valid - # otherwise, the old value is retained - if (csr_value.INT == 1) { - if (valid_interrupt_code?(csr_value.CODE)) { - return csr_value.CODE; - } - return ILLEGAL_WLRL; - } else { - if (valid_exception_code?(csr_value.CODE)) { - return csr_value.CODE; - } - return ILLEGAL_WLRL; + Valid exception codes are: + [separator="!"] + !=== + <%- exception_codes.sort_by { |code| code.num }.each do |code| -%> + ! <%= code.num %> ! <%= code.name %> + <%- end -%> + !=== + type: RW-RH + sw_write(csr_value): | + # the write only holds if the INT/CODE combination is valid + # otherwise, the old value is retained + if (csr_value.INT == 1) { + if (valid_interrupt_code?(csr_value.CODE)) { + return csr_value.CODE; + } + return ILLEGAL_WLRL; + } else { + if (valid_exception_code?(csr_value.CODE)) { + return csr_value.CODE; } - reset_value: UNDEFINED_LEGAL + return ILLEGAL_WLRL; + } + reset_value: UNDEFINED_LEGAL diff --git a/arch/csr/vsepc.yaml b/arch/csr/vsepc.yaml index 9a7a35581..816cb02e0 100644 --- a/arch/csr/vsepc.yaml +++ b/arch/csr/vsepc.yaml @@ -1,44 +1,46 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -vsepc: - long_name: Virtual Supervisor Exception Program Counter - address: 0x241 - virtual_address: 0x141 - priv_mode: VS - length: 64 - description: | - Written with the PC of an instruction on an exception or interrupt taken in VS-mode. +$schema: "csr_schema.json#" +kind: csr +name: vsepc +long_name: Virtual Supervisor Exception Program Counter +address: 0x241 +virtual_address: 0x141 +priv_mode: VS +length: 64 +description: | + Written with the PC of an instruction on an exception or interrupt taken in VS-mode. - Also controls where the hart jumps on an exception return from VS-mode. - definedBy: H - fields: - PC: - location: 63-0 - description: | - When a trap is taken into VS-mode, `vsepc.PC` is written with the virtual address of the - instruction that was interrupted or that encountered the exception. - Otherwise, `vsepc.PC` is never written by the implementation, though it may be explicitly written - by software. + Also controls where the hart jumps on an exception return from VS-mode. +definedBy: H +fields: + PC: + location: 63-0 + description: | + When a trap is taken into VS-mode, `vsepc.PC` is written with the virtual address of the + instruction that was interrupted or that encountered the exception. + Otherwise, `vsepc.PC` is never written by the implementation, though it may be explicitly written + by software. - On an exception retun from VS-mode (from the SRET instruction), - control transfers to the virtual address read out of `vsepc.PC`. + On an exception retun from VS-mode (from the SRET instruction), + control transfers to the virtual address read out of `vsepc.PC`. - Because PCs are always <% if ext?(:C) %>halfword<% else %>word<% end %>-aligned, - <% if ext?(:C) %>bit 0<% else %>bits 1:0<% end %> of `vsepc.PC` are always - read-only 0. + Because PCs are always <% if ext?(:C) %>halfword<% else %>word<% end %>-aligned, + <% if ext?(:C) %>bit 0<% else %>bits 1:0<% end %> of `vsepc.PC` are always + read-only 0. - [when,"ext?(:C) && MUTABLE_MISA_C == true"] - When `misa.C` is clear, bit 1 is masked to zero. Writes to bit 1 are still captured, and - may be visible on the next read with `misa.C` is set. + [when,"ext?(:C) && MUTABLE_MISA_C == true"] + When `misa.C` is clear, bit 1 is masked to zero. Writes to bit 1 are still captured, and + may be visible on the next read with `misa.C` is set. - Holds bits 63:<%= ext?(:C) ? 2 : 1 %> of the virtual address associated with an exception. - type: RW-RH - sw_write(csr_value): | - return csr_value.PC & ~64'b1; - reset_value: UNDEFINED_LEGAL - sw_read(): | - if (implemented?(ExtensionName::C) && CSR[misa].C == 1'b1) { - return CSR[sepc].PC & ~64'b1; - } else { - return CSR[sepc].PC; - } + Holds bits 63:<%= ext?(:C) ? 2 : 1 %> of the virtual address associated with an exception. + type: RW-RH + sw_write(csr_value): | + return csr_value.PC & ~64'b1; + reset_value: UNDEFINED_LEGAL +sw_read(): | + if (implemented?(ExtensionName::C) && CSR[misa].C == 1'b1) { + return CSR[sepc].PC & ~64'b1; + } else { + return CSR[sepc].PC; + } diff --git a/arch/csr/vsstatus.yaml b/arch/csr/vsstatus.yaml index b31f33004..9a3a9d72b 100644 --- a/arch/csr/vsstatus.yaml +++ b/arch/csr/vsstatus.yaml @@ -1,211 +1,213 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -vsstatus: - long_name: Virtual Supervisor Status - address: 0x200 - virtual_address: 0x100 - priv_mode: VS - length: VSXLEN - description: | - The vsstatus register tracks and controls the hart's current operating state. - - It is VS-mode's version of `sstatus`, and substitutes for it when in VS-mode - (_i.e._, in VS-mode CSR address 0x100 is `vsstatus`, not `sstatus`). - - Unlike the relationship between `sstatus` and `mstatus`, none of the bits in `vsstatus` are - aliases of another field. - definedBy: H - fields: - SD: - location_rv64: 63 - location_rv32: 31 - description: | - *State Dirty* - - Read-only bit that summarizes whether any of the - `vsstatus.FS`, <% if ext?(:V) %> `vsstatus.VS`, <% end %> or `vsstatus.XS` - fields signal the presence of some dirty state - (_i.e._, any of them hold the value `11`). - - This bit is _not_ an alias of `mstatus.SD` since - it only reflects the state visible to VS-mode - (_e.g._, `status.FS` does not affect `vsstatus.SD`). - type: RO-H - reset_value: UNDEFINED_LEGAL - affectedBy: [F, D, V] - UXL: - location: 33-32 - base: 64 - description: | - *VU-mode XLEN* - - Sets the effective XLEN for VU-mode (0 = 32-bit, 1 = 64-bit, 2 = 128-bit). - - [when,"VUXLEN == 32"] - Since the hart only supports VUXLEN==32, this is hardwired to 0. - - [when,"VUXLEN == 64"] - Since the hart only supports VUXLEN==64, this is hardwired to 1. - - type(): | - return (VUXLEN == 3264) ? CsrFieldType::RW : CsrFieldType::RO; - reset_value(): | - return (VUXLEN == 3264) ? UNDEFINED_LEGAL : VUXLEN; - MXR: - alias: mstatus.MXR - location: 19 - description: | - *Make eXecutable Readable* - - Makes it possible to read executable pages when loading from effective VU-mode or VS-mode - (normally, executable pages are not readable). - - * When 1, load in effective VU-mode or VS-mode from pages marked readable *or executable* - are allowed as long as the page is marked readable (or executable and `status.MXR` is set) in the - G-stage translation. - * When 0, load in effective VU-mode or VS-mode from pages marked executable raise a - Page Fault exception (unless `sstatus.MXR` is also set, in which case the above applies). - - 'vsstatus.MXR' affects all loads that operate under effective VU-mode or VS-mode: - - * All loads in VU-mode - * All loads in VS-mode - * Loads in M-mode when `mstatus.MPRV` == 1, `mstatus.MPV` == 1, and `mstatus.MPP`[1] == 0 - * Loads generated by one of the `hlv.*` instructions. - - type: RW - definedBy: S - reset_value: UNDEFINED_LEGAL - SUM: - location: 18 - description: | - *permit Supervisor Memory Access* - - Allows VS-mode to read user pages. - - Applies to the following loads and stores: - - * All loads and stores in VS-mode. - * All loads and stores in M-mode when `mstatus.MPRV` == 1, `mstatus.MPP` == 1, and `mstatus.MPV` == 1 - * Loads and stores generated by one of the `hlv.*`, `hlvx.*`, or `hsv.*` instructions. - - When `vsstatus.SUM` is 0, the loads and stores from the above categories cause an - `Illegal Instruction` exception if they access a user page during VS-level translation. - Otherwise, a load or store from the above categories is permitted to acess a user page - during VS-level translation. - - type: RW - definedBy: S - reset_value: UNDEFINED_LEGAL - XS: - alias: mstatus.XS - location: 16-15 - description: | - *Custom (X) extension context Status* - - Summarizes the current state of any custom extension state. - Either 0 - Off, 1 - Initial, 2 - Clean, 3 - Dirty. - Since there are no custom extensions, this field is read-only 0. - type: RO - reset_value: 0 - FS: - location: 14-13 - description: | - *Floating point context status* - - When 0, floating point instructions (from F and D extensions) in VS-mode or VU-mode are disabled, - and cause ILLEGAL INSTRUCTION exceptions. - Floating point instructions in all modes, including VS-mode and VU-mode, - are similarly disabled when `mstatus.FS` is clear. - - When a floating point register, or the `fcsr` register is written in VS-mode or VU-mode, - `vsstatus.FS` is written with the value 3. - - Values 1 and 2 are valid write values for software, but are not interpreted by hardware - other than to possibly enable a previously-disabled floating point unit. - type: RW-H - definedBy: F - reset_value: UNDEFINED_LEGAL - VS: - location: 10-9 - description: | - *Vector context status* - - When 0, vector instructions (from the V extension) are disabled, and cause ILLEGAL INSTRUCTION exceptions. - When a vector register or vector CSR is written, VS obtains the value 3. - Values 1 and 2 are valid write values for software, but are not interpreted by hardware - other than to possibly enable a previously-disabled vector unit. - type: RW-H - reset_value: UNDEFINED_LEGAL - definedBy: V - SPP: - location: 8 - description: | - *VS-mode Previous Privilege* - - Written with the prior nominal privilege level (_i.e._, 0 for VU-mode and 1 for VS-mode) - when entering VS-mode from an exception/interrupt. - Can also be written by software without immediate side-effect. - - On a return from an exception from VS-mode, the machine will enter the nominal privilege level - stored in `vsstatus.SPP`. - type: RW-H - reset_value: UNDEFINED_LEGAL - UBE: - location: 6 - description: | - *VU-mode Big Endian* - - Controls the endianness of VU-mode (0 = little, 1 = big). - - [when,"VU_MODE_ENDIANESS == 'little'"] - Since the CPU does not support big endian, this is hardwired to 0. - - [when,"VU_MODE_ENDIANESS == 'big'"] - Since the CPU does not support big endian, this is hardwired to 1. - type(): | - return (VU_MODE_ENDIANESS == "dynamic") ? CsrFieldType::RW : CsrFieldType::RO; - definedBy: S - reset_value(): | - if (VU_MODE_ENDIANESS == "little") { - # little endian - return 0; - } else if (VU_MODE_ENDIANESS == "big") { - # big endian - return 1; - } else { - # mutable - return UNDEFINED_LEGAL; - } - SPIE: - location: 5 - description: | - *VS-mode Previous Interrupt Enable* - - Written by hardware in two cases: - - * Written with prior value of `vsstatus.SIE` when entering VS-mode from an exception/interrupt. - * Writen with the value 1 when returning from an exception in VS-mode (via the `sret` instruction). - - Can also be written by software without immediate side effect. - - Other than serving as a record of nested traps as described above, `vsstatus.SPIE` does not affect execution. - type: RW-H - definedBy: S - reset_value: UNDEFINED_LEGAL - SIE: - location: 1 - description: | - *VS-mode Interrupt Enable* - - Written by hardware in two cases: - - * Written with the value 0 when entering VS-mode from an exception/interrupt. - * Written with the prior value of `vsstatus.SPIE` when returning from an exeception in VS-mode (via `sret`). - - Affects execution by: - - * When 0, all VS-mode interrupts are disabled when the current privilege level is VS ((H)S-mode and M-mode interrupts are still enabled). - * When 1, VS-mode interrupts that are not otherwise disabled with a field in `vsie` are enabled. - type: RW-H - reset_value: UNDEFINED_LEGAL +$schema: "csr_schema.json#" +kind: csr +name: vsstatus +long_name: Virtual Supervisor Status +address: 0x200 +virtual_address: 0x100 +priv_mode: VS +length: VSXLEN +description: | + The vsstatus register tracks and controls the hart's current operating state. + + It is VS-mode's version of `sstatus`, and substitutes for it when in VS-mode + (_i.e._, in VS-mode CSR address 0x100 is `vsstatus`, not `sstatus`). + + Unlike the relationship between `sstatus` and `mstatus`, none of the bits in `vsstatus` are + aliases of another field. +definedBy: H +fields: + SD: + location_rv64: 63 + location_rv32: 31 + description: | + *State Dirty* + + Read-only bit that summarizes whether any of the + `vsstatus.FS`, <% if ext?(:V) %> `vsstatus.VS`, <% end %> or `vsstatus.XS` + fields signal the presence of some dirty state + (_i.e._, any of them hold the value `11`). + + This bit is _not_ an alias of `mstatus.SD` since + it only reflects the state visible to VS-mode + (_e.g._, `status.FS` does not affect `vsstatus.SD`). + type: RO-H + reset_value: UNDEFINED_LEGAL + affectedBy: [F, D, V] + UXL: + location: 33-32 + base: 64 + description: | + *VU-mode XLEN* + + Sets the effective XLEN for VU-mode (0 = 32-bit, 1 = 64-bit, 2 = 128-bit). + + [when,"VUXLEN == 32"] + Since the hart only supports VUXLEN==32, this is hardwired to 0. + + [when,"VUXLEN == 64"] + Since the hart only supports VUXLEN==64, this is hardwired to 1. + + type(): | + return (VUXLEN == 3264) ? CsrFieldType::RW : CsrFieldType::RO; + reset_value(): | + return (VUXLEN == 3264) ? UNDEFINED_LEGAL : VUXLEN; + MXR: + alias: mstatus.MXR + location: 19 + description: | + *Make eXecutable Readable* + + Makes it possible to read executable pages when loading from effective VU-mode or VS-mode + (normally, executable pages are not readable). + + * When 1, load in effective VU-mode or VS-mode from pages marked readable *or executable* + are allowed as long as the page is marked readable (or executable and `status.MXR` is set) in the + G-stage translation. + * When 0, load in effective VU-mode or VS-mode from pages marked executable raise a + Page Fault exception (unless `sstatus.MXR` is also set, in which case the above applies). + + 'vsstatus.MXR' affects all loads that operate under effective VU-mode or VS-mode: + + * All loads in VU-mode + * All loads in VS-mode + * Loads in M-mode when `mstatus.MPRV` == 1, `mstatus.MPV` == 1, and `mstatus.MPP`[1] == 0 + * Loads generated by one of the `hlv.*` instructions. + + type: RW + definedBy: S + reset_value: UNDEFINED_LEGAL + SUM: + location: 18 + description: | + *permit Supervisor Memory Access* + + Allows VS-mode to read user pages. + + Applies to the following loads and stores: + + * All loads and stores in VS-mode. + * All loads and stores in M-mode when `mstatus.MPRV` == 1, `mstatus.MPP` == 1, and `mstatus.MPV` == 1 + * Loads and stores generated by one of the `hlv.*`, `hlvx.*`, or `hsv.*` instructions. + + When `vsstatus.SUM` is 0, the loads and stores from the above categories cause an + `Illegal Instruction` exception if they access a user page during VS-level translation. + Otherwise, a load or store from the above categories is permitted to acess a user page + during VS-level translation. + + type: RW + definedBy: S + reset_value: UNDEFINED_LEGAL + XS: + alias: mstatus.XS + location: 16-15 + description: | + *Custom (X) extension context Status* + + Summarizes the current state of any custom extension state. + Either 0 - Off, 1 - Initial, 2 - Clean, 3 - Dirty. + Since there are no custom extensions, this field is read-only 0. + type: RO + reset_value: 0 + FS: + location: 14-13 + description: | + *Floating point context status* + + When 0, floating point instructions (from F and D extensions) in VS-mode or VU-mode are disabled, + and cause ILLEGAL INSTRUCTION exceptions. + Floating point instructions in all modes, including VS-mode and VU-mode, + are similarly disabled when `mstatus.FS` is clear. + + When a floating point register, or the `fcsr` register is written in VS-mode or VU-mode, + `vsstatus.FS` is written with the value 3. + + Values 1 and 2 are valid write values for software, but are not interpreted by hardware + other than to possibly enable a previously-disabled floating point unit. + type: RW-H + definedBy: F + reset_value: UNDEFINED_LEGAL + VS: + location: 10-9 + description: | + *Vector context status* + + When 0, vector instructions (from the V extension) are disabled, and cause ILLEGAL INSTRUCTION exceptions. + When a vector register or vector CSR is written, VS obtains the value 3. + Values 1 and 2 are valid write values for software, but are not interpreted by hardware + other than to possibly enable a previously-disabled vector unit. + type: RW-H + reset_value: UNDEFINED_LEGAL + definedBy: V + SPP: + location: 8 + description: | + *VS-mode Previous Privilege* + + Written with the prior nominal privilege level (_i.e._, 0 for VU-mode and 1 for VS-mode) + when entering VS-mode from an exception/interrupt. + Can also be written by software without immediate side-effect. + + On a return from an exception from VS-mode, the machine will enter the nominal privilege level + stored in `vsstatus.SPP`. + type: RW-H + reset_value: UNDEFINED_LEGAL + UBE: + location: 6 + description: | + *VU-mode Big Endian* + + Controls the endianness of VU-mode (0 = little, 1 = big). + + [when,"VU_MODE_ENDIANESS == 'little'"] + Since the CPU does not support big endian, this is hardwired to 0. + + [when,"VU_MODE_ENDIANESS == 'big'"] + Since the CPU does not support big endian, this is hardwired to 1. + type(): | + return (VU_MODE_ENDIANESS == "dynamic") ? CsrFieldType::RW : CsrFieldType::RO; + definedBy: S + reset_value(): | + if (VU_MODE_ENDIANESS == "little") { + # little endian + return 0; + } else if (VU_MODE_ENDIANESS == "big") { + # big endian + return 1; + } else { + # mutable + return UNDEFINED_LEGAL; + } + SPIE: + location: 5 + description: | + *VS-mode Previous Interrupt Enable* + + Written by hardware in two cases: + + * Written with prior value of `vsstatus.SIE` when entering VS-mode from an exception/interrupt. + * Writen with the value 1 when returning from an exception in VS-mode (via the `sret` instruction). + + Can also be written by software without immediate side effect. + + Other than serving as a record of nested traps as described above, `vsstatus.SPIE` does not affect execution. + type: RW-H + definedBy: S + reset_value: UNDEFINED_LEGAL + SIE: + location: 1 + description: | + *VS-mode Interrupt Enable* + + Written by hardware in two cases: + + * Written with the value 0 when entering VS-mode from an exception/interrupt. + * Written with the prior value of `vsstatus.SPIE` when returning from an exeception in VS-mode (via `sret`). + + Affects execution by: + + * When 0, all VS-mode interrupts are disabled when the current privilege level is VS ((H)S-mode and M-mode interrupts are still enabled). + * When 1, VS-mode interrupts that are not otherwise disabled with a field in `vsie` are enabled. + type: RW-H + reset_value: UNDEFINED_LEGAL diff --git a/arch/csr/vstval.yaml b/arch/csr/vstval.yaml index 2779e1e57..bc1cbfc87 100644 --- a/arch/csr/vstval.yaml +++ b/arch/csr/vstval.yaml @@ -1,97 +1,99 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -vstval: - long_name: Virtual supervisor Trap Value - address: 0x243 - virtual_address: 0x143 - description: Holds trap-specific information - priv_mode: S - length: VSXLEN - definedBy: H - fields: - VALUE: - location_rv32: 31-0 - location_rv64: 63-0 - description: | - Written with trap-specific information when a trap is taken into VS-mode. +$schema: "csr_schema.json#" +kind: csr +name: vstval +long_name: Virtual supervisor Trap Value +address: 0x243 +virtual_address: 0x143 +description: Holds trap-specific information +priv_mode: S +length: VSXLEN +definedBy: H +fields: + VALUE: + location_rv32: 31-0 + location_rv64: 63-0 + description: | + Written with trap-specific information when a trap is taken into VS-mode. - The values are: + The values are: - [separator="!"] - !=== - ! Exception type ! Value + [separator="!"] + !=== + ! Exception type ! Value - ! [0] Instruction address misaligned ! The misaligned virtual PC (same as the value written to `mepc`). - ! [1] Instruction access fault ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the access fault <%- unless ext?(:C) -%>(same as the value written to `mepc`)<%- end -%>. - ! [2] Illegal Instruction ! The encoding of the illegal instruction. - ! [3] Breakpoint - a! [when,"REPORT_VA_IN_VSTVAL_ON_BREAKPOINT == true"] - When caused by an EBREAK instruction, the virtual PC of the breakpoint instruction. - - [when,"REPORT_VA_IN_VSTVAL_ON_BREAKPOINT == false"] - When caused by an EBREAK instruction, zero. + ! [0] Instruction address misaligned ! The misaligned virtual PC (same as the value written to `mepc`). + ! [1] Instruction access fault ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the access fault <%- unless ext?(:C) -%>(same as the value written to `mepc`)<%- end -%>. + ! [2] Illegal Instruction ! The encoding of the illegal instruction. + ! [3] Breakpoint + a! [when,"REPORT_VA_IN_VSTVAL_ON_BREAKPOINT == true"] + When caused by an EBREAK instruction, the virtual PC of the breakpoint instruction. + + [when,"REPORT_VA_IN_VSTVAL_ON_BREAKPOINT == false"] + When caused by an EBREAK instruction, zero. - When caused by a data address (_i.e._, watchpoint) breakpoint, the faulting virtual address. - When caused by an instruction address breakpoint, the faulting virtual PC. - ! [4] Load address misaligned ! The misaligned virtual load address. - ! [5] Load access fault - ! The part of virtual load address causing in the access fault. + When caused by a data address (_i.e._, watchpoint) breakpoint, the faulting virtual address. + When caused by an instruction address breakpoint, the faulting virtual PC. + ! [4] Load address misaligned ! The misaligned virtual load address. + ! [5] Load access fault + ! The part of virtual load address causing in the access fault. - When the load is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, - address + 4 is reported). + When the load is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, + address + 4 is reported). - (Even though the access fault arises on a physical address, the virtual address is reported) - ! [6] Store/AMO address misaligned ! The misaligned virtual store/AMO address. - ! [7] Store/AMO access fault - ! The virtual store/AMO address causing the access fault. - - When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, - address + 4 is reported). + (Even though the access fault arises on a physical address, the virtual address is reported) + ! [6] Store/AMO address misaligned ! The misaligned virtual store/AMO address. + ! [7] Store/AMO access fault + ! The virtual store/AMO address causing the access fault. + + When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, + address + 4 is reported). - (Even though the access fault arises on a physical address, the virtual address is reported) - ! [8] Environment call from U-mode <% if ext?(:H) %>or VU-mode<% end %> ! Zero - ! [9] Environment call from (H)S-mode ! Zero - <%- if ext?(:H) -%> - ! [10] Environment call from VS-mode ! Zero - <%- end -%> - ! [12] Instruction page fault - ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the page fault - <% unless ext?(:C) %>(same as the value written to `mepc`)<% end %>. - ! [13] Load page fault - ! The part of the virtual load address causing in the page fault. - - When the load is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, address + 4 is reported). - ! [15] Store/AMO page fault - ! The virtual store/AMO address causing in the page fault. - - When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, address + 4 is reported). - <%- if ext?(:H) -%> - ! [20] Instruction guest-page fault - ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the fault <% unless ext?(:C) %>(same as the value written to `mepc`)<% end %>. + (Even though the access fault arises on a physical address, the virtual address is reported) + ! [8] Environment call from U-mode <% if ext?(:H) %>or VU-mode<% end %> ! Zero + ! [9] Environment call from (H)S-mode ! Zero + <%- if ext?(:H) -%> + ! [10] Environment call from VS-mode ! Zero + <%- end -%> + ! [12] Instruction page fault + ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the page fault + <% unless ext?(:C) %>(same as the value written to `mepc`)<% end %>. + ! [13] Load page fault + ! The part of the virtual load address causing in the page fault. - The guest physical address is reported in `mtval2`. - ! [21] Load guest-page fault - ! The part of the virtual address causing the fault. + When the load is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, address + 4 is reported). + ! [15] Store/AMO page fault + ! The virtual store/AMO address causing in the page fault. + + When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, address + 4 is reported). + <%- if ext?(:H) -%> + ! [20] Instruction guest-page fault + ! The <% if ext?(:C) %> portion of the <% end %> virtual PC causing the fault <% unless ext?(:C) %>(same as the value written to `mepc`)<% end %>. + + The guest physical address is reported in `mtval2`. + ! [21] Load guest-page fault + ! The part of the virtual address causing the fault. - When the load is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, address + 4 is reported). - - The guest physical address is reported in `mtval2`. - ! [22] Virutal instruction - ! The encoding of the faulting virtual instruction. - ! [23] Store/AMO guest-page fault - ! The part of the virtual address causing the fault. + When the load is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte load is equally split across a page and the fault occurs on the second page, address + 4 is reported). + + The guest physical address is reported in `mtval2`. + ! [22] Virutal instruction + ! The encoding of the faulting virtual instruction. + ! [23] Store/AMO guest-page fault + ! The part of the virtual address causing the fault. + + When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault + (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, address + 4 is reported). - When the store/AMO is misaligned, the reported value is the smallest address on the page causing a fault - (_e.g._, if an 8-byte store is equally split across a page and the fault occurs on the second page, address + 4 is reported). - - The guest physical address is reported in `htval`. - <%- end -%> - !=== + The guest physical address is reported in `htval`. + <%- end -%> + !=== - type: RW-H - reset_value: 0 + type: RW-H + reset_value: 0 diff --git a/arch/csr/vstvec.yaml b/arch/csr/vstvec.yaml index 88f491128..1d77e20b4 100644 --- a/arch/csr/vstvec.yaml +++ b/arch/csr/vstvec.yaml @@ -1,45 +1,47 @@ # yaml-language-server: $schema=../../schemas/csr_schema.json -vstvec: - long_name: Supervisor Trap Vector - address: 0x205 - virtual_address: 0x105 - priv_mode: S - length: 64 - description: Controls where traps jump. - definedBy: H - fields: - BASE: - location: 63-2 - description: | - <%- va_size = ext?(:Sv57) ? 57 : (ext?(:Sv48) ? 49 :39) -%> - Bit 63:0 of the virtual address of the exception vector for any trap taken into VS-mode. +$schema: "csr_schema.json#" +kind: csr +name: vstvec +long_name: Supervisor Trap Vector +address: 0x205 +virtual_address: 0x105 +priv_mode: S +length: 64 +description: Controls where traps jump. +definedBy: H +fields: + BASE: + location: 63-2 + description: | + <%- va_size = ext?(:Sv57) ? 57 : (ext?(:Sv48) ? 49 :39) -%> + Bit 63:0 of the virtual address of the exception vector for any trap taken into VS-mode. - If the base address is written with a non-cannonical address (_i.e._, bits 63:<%= va_size %> do not match bit <%= va_size-1 %>), - the write should be ignored. + If the base address is written with a non-cannonical address (_i.e._, bits 63:<%= va_size %> do not match bit <%= va_size-1 %>), + the write should be ignored. - type: RW-R - sw_write(csr_value): | - # Base spec says that BASE must be 4-byte aligned, which will always be the case - # implementations may put further constraints on BASE when MODE != Direct - # If that is the case, stvec should have an override for the implementation - return csr_value.BASE; - reset_value: 0 - MODE: - location: 1-0 - description: | - Vectoring mode for asynchronous interrupts taken into VS-mode. - - 0 - Direct, 1 - Vectored + type: RW-R + sw_write(csr_value): | + # Base spec says that BASE must be 4-byte aligned, which will always be the case + # implementations may put further constraints on BASE when MODE != Direct + # If that is the case, stvec should have an override for the implementation + return csr_value.BASE; + reset_value: 0 + MODE: + location: 1-0 + description: | + Vectoring mode for asynchronous interrupts taken into VS-mode. + + 0 - Direct, 1 - Vectored - When Direct, all synchronous exceptions and asynchronous interrupts jump to (`vstvec.BASE` << 2). + When Direct, all synchronous exceptions and asynchronous interrupts jump to (`vstvec.BASE` << 2). - When Vectored, asynchronous interrupts jump to (`vstvec.BASE` << 2 + `vscause.CAUSE`*4) while synchronous exceptions continue to jump to (`vstvec.BASE` << 2). - type: RW-R - sw_write(csr_value): | - if (csr_value.MODE == 0 || csr_value.MODE == 1) { - return csr_value.MODE; - } else { - return UNDEFINED_LEGAL_DETERMINISTIC; - } - reset_value: 0 \ No newline at end of file + When Vectored, asynchronous interrupts jump to (`vstvec.BASE` << 2 + `vscause.CAUSE`*4) while synchronous exceptions continue to jump to (`vstvec.BASE` << 2). + type: RW-R + sw_write(csr_value): | + if (csr_value.MODE == 0 || csr_value.MODE == 1) { + return csr_value.MODE; + } else { + return UNDEFINED_LEGAL_DETERMINISTIC; + } + reset_value: 0 \ No newline at end of file diff --git a/arch/ext/A.yaml b/arch/ext/A.yaml index 1ec21fd28..b857f9d79 100644 --- a/arch/ext/A.yaml +++ b/arch/ext/A.yaml @@ -1,123 +1,125 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -A: - type: unprivileged - long_name: Atomic instructions - company: - name: RISC-V International - url: https://riscv.org - versions: - - version: "2.1.0" - state: ratified - ratification_date: 2019-12 - contributors: - - name: Unknown - email: unknown@void.segfault - company: Unknown - implies: - - [Zaamo, "1.0.0"] - - [Zalrsc, "1.0.0"] - description: | +$schema: "ext_schema.json#" +kind: extension +name: A +type: unprivileged +long_name: Atomic instructions +company: + name: RISC-V International + url: https://riscv.org +versions: +- version: "2.1.0" + state: ratified + ratification_date: 2019-12 + contributors: + - name: Unknown + email: unknown@void.segfault + company: Unknown + implies: + - [Zaamo, "1.0.0"] + - [Zalrsc, "1.0.0"] +description: | - The atomic-instruction extension, named `A`, contains - instructions that atomically read-modify-write memory to support - synchronization between multiple RISC-V harts running in the same memory - space. The two forms of atomic instruction provided are - load-reserved/store-conditional instructions and atomic fetch-and-op - memory instructions. Both types of atomic instruction support various - memory consistency orderings including unordered, acquire, release, and - sequentially consistent semantics. These instructions allow RISC-V to - support the RCsc memory consistency model. cite:[Gharachorloo90memoryconsistency] + The atomic-instruction extension, named `A`, contains + instructions that atomically read-modify-write memory to support + synchronization between multiple RISC-V harts running in the same memory + space. The two forms of atomic instruction provided are + load-reserved/store-conditional instructions and atomic fetch-and-op + memory instructions. Both types of atomic instruction support various + memory consistency orderings including unordered, acquire, release, and + sequentially consistent semantics. These instructions allow RISC-V to + support the RCsc memory consistency model. cite:[Gharachorloo90memoryconsistency] - [NOTE] - ==== - After much debate, the language community and architecture community - appear to have finally settled on release consistency as the standard - memory consistency model and so the RISC-V atomic support is built - around this model. - ==== + [NOTE] + ==== + After much debate, the language community and architecture community + appear to have finally settled on release consistency as the standard + memory consistency model and so the RISC-V atomic support is built + around this model. + ==== - The `A` extension comprises instructions provided by the `Zaamo` and `Zalrsc` - extensions. + The `A` extension comprises instructions provided by the `Zaamo` and `Zalrsc` + extensions. - = Specifying Ordering of Atomic Instructions + = Specifying Ordering of Atomic Instructions - The base RISC-V ISA has a relaxed memory model, with the `FENCE` - instruction used to impose additional ordering constraints. The address - space is divided by the execution environment into memory and I/O - domains, and the `FENCE` instruction provides options to order accesses to - one or both of these two address domains. + The base RISC-V ISA has a relaxed memory model, with the `FENCE` + instruction used to impose additional ordering constraints. The address + space is divided by the execution environment into memory and I/O + domains, and the `FENCE` instruction provides options to order accesses to + one or both of these two address domains. - To provide more efficient support for release consistency cite:[Gharachorloo90memoryconsistency], each atomic - instruction has two bits, _aq_ and _rl_, used to specify additional - memory ordering constraints as viewed by other RISC-V harts. The bits - order accesses to one of the two address domains, memory or I/O, - depending on which address domain the atomic instruction is accessing. - No ordering constraint is implied to accesses to the other domain, and a - FENCE instruction should be used to order across both domains. + To provide more efficient support for release consistency cite:[Gharachorloo90memoryconsistency], each atomic + instruction has two bits, _aq_ and _rl_, used to specify additional + memory ordering constraints as viewed by other RISC-V harts. The bits + order accesses to one of the two address domains, memory or I/O, + depending on which address domain the atomic instruction is accessing. + No ordering constraint is implied to accesses to the other domain, and a + FENCE instruction should be used to order across both domains. - If both bits are clear, no additional ordering constraints are imposed - on the atomic memory operation. If only the _aq_ bit is set, the atomic - memory operation is treated as an _acquire_ access, i.e., no following - memory operations on this RISC-V hart can be observed to take place - before the acquire memory operation. If only the _rl_ bit is set, the - atomic memory operation is treated as a _release_ access, i.e., the - release memory operation cannot be observed to take place before any - earlier memory operations on this RISC-V hart. If both the _aq_ and _rl_ - bits are set, the atomic memory operation is _sequentially consistent_ - and cannot be observed to happen before any earlier memory operations or - after any later memory operations in the same RISC-V hart and to the - same address domain. - params: - MISALIGNED_AMO: - description: | - whether or not the implementation supports misaligned atomics in main memory - schema: - type: boolean - LRSC_RESERVATION_STRATEGY: - description: | - Strategy used to handle reservation sets. + If both bits are clear, no additional ordering constraints are imposed + on the atomic memory operation. If only the _aq_ bit is set, the atomic + memory operation is treated as an _acquire_ access, i.e., no following + memory operations on this RISC-V hart can be observed to take place + before the acquire memory operation. If only the _rl_ bit is set, the + atomic memory operation is treated as a _release_ access, i.e., the + release memory operation cannot be observed to take place before any + earlier memory operations on this RISC-V hart. If both the _aq_ and _rl_ + bits are set, the atomic memory operation is _sequentially consistent_ + and cannot be observed to happen before any earlier memory operations or + after any later memory operations in the same RISC-V hart and to the + same address domain. +params: + MISALIGNED_AMO: + description: | + whether or not the implementation supports misaligned atomics in main memory + schema: + type: boolean + LRSC_RESERVATION_STRATEGY: + description: | + Strategy used to handle reservation sets. - * "reserve naturally-aligned 64-byte region": Always reserve the 64-byte block containing the LR/SC address - * "reserve naturally-aligned 128-byte region": Always reserve the 128-byte block containing the LR/SC address - * "reserve exactly enough to cover the access": Always reserve exactly the LR/SC access, and no more - * "custom": Custom behavior, leading to an 'unpredictable' call on any LR/SC - schema: - type: string - enum: - - reserve naturally-aligned 64-byte region - - reserve naturally-aligned 128-byte region - - reserve exactly enough to cover the access - - custom - LRSC_FAIL_ON_VA_SYNONYM: - description: | - Whether or not an `sc.l`/`sc.d` will fail if its VA does not match the VA of the prior - `lr.l`/`lr.d`, even if the physical address of the SC and LR are the same - schema: - type: boolean - LRSC_MISALIGNED_BEHAVIOR: - description: | - What to do when an LR/SC address is misaligned and MISALIGNED_AMO == false. + * "reserve naturally-aligned 64-byte region": Always reserve the 64-byte block containing the LR/SC address + * "reserve naturally-aligned 128-byte region": Always reserve the 128-byte block containing the LR/SC address + * "reserve exactly enough to cover the access": Always reserve exactly the LR/SC access, and no more + * "custom": Custom behavior, leading to an 'unpredictable' call on any LR/SC + schema: + type: string + enum: + - reserve naturally-aligned 64-byte region + - reserve naturally-aligned 128-byte region + - reserve exactly enough to cover the access + - custom + LRSC_FAIL_ON_VA_SYNONYM: + description: | + Whether or not an `sc.l`/`sc.d` will fail if its VA does not match the VA of the prior + `lr.l`/`lr.d`, even if the physical address of the SC and LR are the same + schema: + type: boolean + LRSC_MISALIGNED_BEHAVIOR: + description: | + What to do when an LR/SC address is misaligned and MISALIGNED_AMO == false. - * 'always raise misaligned exception': self-explainitory - * 'always raise access fault': self-explainitory - * 'custom': Custom behavior; misaligned LR/SC may sometimes raise a misaligned exception and sometimes raise a access fault. Will lead to an 'unpredictable' call on any misaligned LR/SC access - schema: - type: string - enum: - - always raise misaligned exception - - always raise access fault - - custom - LRSC_FAIL_ON_NON_EXACT_LRSC: - description: | - Whether or not a Store Conditional fails if its physical address and size do not - exactly match the physical address and size of the last Load Reserved in program order - (independent of whether or not the SC is in the current reservation set) - schema: - type: boolean - MUTABLE_MISA_A: - description: | - When the `A` extensions is supported, indicates whether or not - the extension can be disabled in the `misa.A` bit. - schema: - type: boolean + * 'always raise misaligned exception': self-explainitory + * 'always raise access fault': self-explainitory + * 'custom': Custom behavior; misaligned LR/SC may sometimes raise a misaligned exception and sometimes raise a access fault. Will lead to an 'unpredictable' call on any misaligned LR/SC access + schema: + type: string + enum: + - always raise misaligned exception + - always raise access fault + - custom + LRSC_FAIL_ON_NON_EXACT_LRSC: + description: | + Whether or not a Store Conditional fails if its physical address and size do not + exactly match the physical address and size of the last Load Reserved in program order + (independent of whether or not the SC is in the current reservation set) + schema: + type: boolean + MUTABLE_MISA_A: + description: | + When the `A` extensions is supported, indicates whether or not + the extension can be disabled in the `misa.A` bit. + schema: + type: boolean diff --git a/arch/ext/B.yaml b/arch/ext/B.yaml index 50cb8aeeb..b7eac4986 100644 --- a/arch/ext/B.yaml +++ b/arch/ext/B.yaml @@ -1,37 +1,39 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -B: - type: unprivileged - long_name: Bitmanipulation instructions - company: - name: RISC-V International - url: https://riscv.org - doc_license: - name: Creative Commons Attribution 4.0 International License - url: https://creativecommons.org/licenses/by/4.0/ - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2024-04 - contributors: - - name: Ved Shanbhogue - email: ved@rivosinc.com - company: Rivos, Inc. - url: https://drive.google.com/file/d/1SgLoasaBjs5WboQMaU3wpHkjUwV71UZn/view - implies: - - [Zba, "1.0.0"] - - [Zbb, "1.0.0"] - - [Zbs, "1.0.0"] - description: | - The B standard extension comprises instructions provided by the `Zba`, `Zbb`, and `Zbs` extensions. +$schema: "ext_schema.json#" +kind: extension +name: B +type: unprivileged +long_name: Bitmanipulation instructions +company: + name: RISC-V International + url: https://riscv.org +doc_license: + name: Creative Commons Attribution 4.0 International License + url: https://creativecommons.org/licenses/by/4.0/ +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2024-04 + contributors: + - name: Ved Shanbhogue + email: ved@rivosinc.com + company: Rivos, Inc. + url: https://drive.google.com/file/d/1SgLoasaBjs5WboQMaU3wpHkjUwV71UZn/view + implies: + - [Zba, "1.0.0"] + - [Zbb, "1.0.0"] + - [Zbs, "1.0.0"] +description: | + The B standard extension comprises instructions provided by the `Zba`, `Zbb`, and `Zbs` extensions. - Bit 1 of the `misa` register encodes the presence of the B standard extension. When `misa.B` is 1, - the implementation supports the instructions provided by the `Zba`, `Zbb`, and `Zbs` extensions. - When `misa.B` is 0, it indicates that the implementation may not support one or more of the - `Zba`, `Zbb`, or `Zbs` extensions. - params: - MUTABLE_MISA_B: - description: | - Indicates whether or not the `B` extension can be disabled with the `misa.B` bit. - schema: - type: boolean + Bit 1 of the `misa` register encodes the presence of the B standard extension. When `misa.B` is 1, + the implementation supports the instructions provided by the `Zba`, `Zbb`, and `Zbs` extensions. + When `misa.B` is 0, it indicates that the implementation may not support one or more of the + `Zba`, `Zbb`, or `Zbs` extensions. +params: + MUTABLE_MISA_B: + description: | + Indicates whether or not the `B` extension can be disabled with the `misa.B` bit. + schema: + type: boolean diff --git a/arch/ext/C.yaml b/arch/ext/C.yaml index 3ec544064..5321d7d90 100644 --- a/arch/ext/C.yaml +++ b/arch/ext/C.yaml @@ -1,301 +1,303 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -C: - type: unprivileged - long_name: Compressed instructions - company: - name: RISC-V International - url: https://riscv.org - doc_license: - name: Creative Commons Attribution 4.0 International License - url: https://creativecommons.org/licenses/by/4.0/ - versions: - - version: "2.2.0" - state: ratified - ratification_date: 2019-12 - description: | - The `C` extension reduces static and dynamic code size by - adding short 16-bit instruction encodings for common operations. The C - extension can be added to any of the base ISAs (RV32, RV64, RV128), and - we use the generic term "RVC" to cover any of these. Typically, - 50%-60% of the RISC-V instructions in a program can be replaced with RVC - instructions, resulting in a 25%-30% code-size reduction. +$schema: "ext_schema.json#" +kind: extension +name: C +type: unprivileged +long_name: Compressed instructions +company: + name: RISC-V International + url: https://riscv.org +doc_license: + name: Creative Commons Attribution 4.0 International License + url: https://creativecommons.org/licenses/by/4.0/ +versions: +- version: "2.2.0" + state: ratified + ratification_date: 2019-12 +description: | + The `C` extension reduces static and dynamic code size by + adding short 16-bit instruction encodings for common operations. The C + extension can be added to any of the base ISAs (RV32, RV64, RV128), and + we use the generic term "RVC" to cover any of these. Typically, + 50%-60% of the RISC-V instructions in a program can be replaced with RVC + instructions, resulting in a 25%-30% code-size reduction. - = Overview + = Overview - RVC uses a simple compression scheme that offers shorter 16-bit versions - of common 32-bit RISC-V instructions when: + RVC uses a simple compression scheme that offers shorter 16-bit versions + of common 32-bit RISC-V instructions when: - * the immediate or address offset is small, or - * one of the registers is the zero register (`x0`), the ABI link register - (`x1`), or the ABI stack pointer (`x2`), or - * the destination register and the first source register are identical, or - * the registers used are the 8 most popular ones. + * the immediate or address offset is small, or + * one of the registers is the zero register (`x0`), the ABI link register + (`x1`), or the ABI stack pointer (`x2`), or + * the destination register and the first source register are identical, or + * the registers used are the 8 most popular ones. - The C extension is compatible with all other standard instruction - extensions. The C extension allows 16-bit instructions to be freely - intermixed with 32-bit instructions, with the latter now able to start - on any 16-bit boundary, i.e., IALIGN=16. With the addition of the C - extension, no instructions can raise instruction-address-misaligned - exceptions. + The C extension is compatible with all other standard instruction + extensions. The C extension allows 16-bit instructions to be freely + intermixed with 32-bit instructions, with the latter now able to start + on any 16-bit boundary, i.e., IALIGN=16. With the addition of the C + extension, no instructions can raise instruction-address-misaligned + exceptions. - [NOTE] - ==== - Removing the 32-bit alignment constraint on the original 32-bit - instructions allows significantly greater code density. - ==== + [NOTE] + ==== + Removing the 32-bit alignment constraint on the original 32-bit + instructions allows significantly greater code density. + ==== - The compressed instruction encodings are mostly common across RV32C, - RV64C, and RV128C, but as shown in <>, a few opcodes are used for - different purposes depending on base ISA. For example, the wider - address-space RV64C and RV128C variants require additional opcodes to - compress loads and stores of 64-bit integer values, while RV32C uses the - same opcodes to compress loads and stores of single-precision - floating-point values. Similarly, RV128C requires additional opcodes to - capture loads and stores of 128-bit integer values, while these same - opcodes are used for loads and stores of double-precision floating-point - values in RV32C and RV64C. If the C extension is implemented, the - appropriate compressed floating-point load and store instructions must - be provided whenever the relevant standard floating-point extension (F - and/or D) is also implemented. In addition, RV32C includes a compressed - jump and link instruction to compress short-range subroutine calls, - where the same opcode is used to compress ADDIW for RV64C and RV128C. + The compressed instruction encodings are mostly common across RV32C, + RV64C, and RV128C, but as shown in <>, a few opcodes are used for + different purposes depending on base ISA. For example, the wider + address-space RV64C and RV128C variants require additional opcodes to + compress loads and stores of 64-bit integer values, while RV32C uses the + same opcodes to compress loads and stores of single-precision + floating-point values. Similarly, RV128C requires additional opcodes to + capture loads and stores of 128-bit integer values, while these same + opcodes are used for loads and stores of double-precision floating-point + values in RV32C and RV64C. If the C extension is implemented, the + appropriate compressed floating-point load and store instructions must + be provided whenever the relevant standard floating-point extension (F + and/or D) is also implemented. In addition, RV32C includes a compressed + jump and link instruction to compress short-range subroutine calls, + where the same opcode is used to compress ADDIW for RV64C and RV128C. - [TIP] - ==== - Double-precision loads and stores are a significant fraction of static - and dynamic instructions, hence the motivation to include them in the - RV32C and RV64C encoding. - - Although single-precision loads and stores are not a significant source - of static or dynamic compression for benchmarks compiled for the - currently supported ABIs, for microcontrollers that only provide - hardware single-precision floating-point units and have an ABI that only - supports single-precision floating-point numbers, the single-precision - loads and stores will be used at least as frequently as double-precision - loads and stores in the measured benchmarks. Hence, the motivation to - provide compressed support for these in RV32C. + [TIP] + ==== + Double-precision loads and stores are a significant fraction of static + and dynamic instructions, hence the motivation to include them in the + RV32C and RV64C encoding. + + Although single-precision loads and stores are not a significant source + of static or dynamic compression for benchmarks compiled for the + currently supported ABIs, for microcontrollers that only provide + hardware single-precision floating-point units and have an ABI that only + supports single-precision floating-point numbers, the single-precision + loads and stores will be used at least as frequently as double-precision + loads and stores in the measured benchmarks. Hence, the motivation to + provide compressed support for these in RV32C. - Short-range subroutine calls are more likely in small binaries for - microcontrollers, hence the motivation to include these in RV32C. + Short-range subroutine calls are more likely in small binaries for + microcontrollers, hence the motivation to include these in RV32C. - Although reusing opcodes for different purposes for different base ISAs - adds some complexity to documentation, the impact on implementation - complexity is small even for designs that support multiple base ISAs. - The compressed floating-point load and store variants use the same - instruction format with the same register specifiers as the wider - integer loads and stores. - ==== + Although reusing opcodes for different purposes for different base ISAs + adds some complexity to documentation, the impact on implementation + complexity is small even for designs that support multiple base ISAs. + The compressed floating-point load and store variants use the same + instruction format with the same register specifiers as the wider + integer loads and stores. + ==== - RVC was designed under the constraint that each RVC instruction expands - into a single 32-bit instruction in either the base ISA (RV32I/E, RV64I/E, - or RV128I) or the F and D standard extensions where present. Adopting - this constraint has two main benefits: + RVC was designed under the constraint that each RVC instruction expands + into a single 32-bit instruction in either the base ISA (RV32I/E, RV64I/E, + or RV128I) or the F and D standard extensions where present. Adopting + this constraint has two main benefits: - * Hardware designs can simply expand RVC instructions during decode, - simplifying verification and minimizing modifications to existing - microarchitectures. + * Hardware designs can simply expand RVC instructions during decode, + simplifying verification and minimizing modifications to existing + microarchitectures. - * Compilers can be unaware of the RVC extension and leave code compression - to the assembler and linker, although a compression-aware compiler will - generally be able to produce better results. + * Compilers can be unaware of the RVC extension and leave code compression + to the assembler and linker, although a compression-aware compiler will + generally be able to produce better results. - [NOTE] - ==== - We felt the multiple complexity reductions of a simple one-one mapping - between C and base IFD instructions far outweighed the potential gains - of a slightly denser encoding that added additional instructions only - supported in the C extension, or that allowed encoding of multiple IFD - instructions in one C instruction. - ==== + [NOTE] + ==== + We felt the multiple complexity reductions of a simple one-one mapping + between C and base IFD instructions far outweighed the potential gains + of a slightly denser encoding that added additional instructions only + supported in the C extension, or that allowed encoding of multiple IFD + instructions in one C instruction. + ==== - It is important to note that the C extension is not designed to be a - stand-alone ISA, and is meant to be used alongside a base ISA. + It is important to note that the C extension is not designed to be a + stand-alone ISA, and is meant to be used alongside a base ISA. - [TIP] - ==== - Variable-length instruction sets have long been used to improve code - density. For example, the IBM Stretch cite:[stretch], developed in the late 1950s, had - an ISA with 32-bit and 64-bit instructions, where some of the 32-bit - instructions were compressed versions of the full 64-bit instructions. - Stretch also employed the concept of limiting the set of registers that - were addressable in some of the shorter instruction formats, with short - branch instructions that could only refer to one of the index registers. - The later IBM 360 architecture cite:[ibm360] supported a simple variable-length - instruction encoding with 16-bit, 32-bit, or 48-bit instruction formats. + [TIP] + ==== + Variable-length instruction sets have long been used to improve code + density. For example, the IBM Stretch cite:[stretch], developed in the late 1950s, had + an ISA with 32-bit and 64-bit instructions, where some of the 32-bit + instructions were compressed versions of the full 64-bit instructions. + Stretch also employed the concept of limiting the set of registers that + were addressable in some of the shorter instruction formats, with short + branch instructions that could only refer to one of the index registers. + The later IBM 360 architecture cite:[ibm360] supported a simple variable-length + instruction encoding with 16-bit, 32-bit, or 48-bit instruction formats. - In 1963, CDC introduced the Cray-designed CDC 6600 cite:[cdc6600], a precursor to RISC - architectures, that introduced a register-rich load-store architecture - with instructions of two lengths, 15-bits and 30-bits. The later Cray-1 - design used a very similar instruction format, with 16-bit and 32-bit - instruction lengths. + In 1963, CDC introduced the Cray-designed CDC 6600 cite:[cdc6600], a precursor to RISC + architectures, that introduced a register-rich load-store architecture + with instructions of two lengths, 15-bits and 30-bits. The later Cray-1 + design used a very similar instruction format, with 16-bit and 32-bit + instruction lengths. - The initial RISC ISAs from the 1980s all picked performance over code - size, which was reasonable for a workstation environment, but not for - embedded systems. Hence, both ARM and MIPS subsequently made versions of - the ISAs that offered smaller code size by offering an alternative - 16-bit wide instruction set instead of the standard 32-bit wide - instructions. The compressed RISC ISAs reduced code size relative to - their starting points by about 25-30%, yielding code that was - significantly smaller than 80x86. This result surprised some, as their - intuition was that the variable-length CISC ISA should be smaller than - RISC ISAs that offered only 16-bit and 32-bit formats. + The initial RISC ISAs from the 1980s all picked performance over code + size, which was reasonable for a workstation environment, but not for + embedded systems. Hence, both ARM and MIPS subsequently made versions of + the ISAs that offered smaller code size by offering an alternative + 16-bit wide instruction set instead of the standard 32-bit wide + instructions. The compressed RISC ISAs reduced code size relative to + their starting points by about 25-30%, yielding code that was + significantly smaller than 80x86. This result surprised some, as their + intuition was that the variable-length CISC ISA should be smaller than + RISC ISAs that offered only 16-bit and 32-bit formats. - Since the original RISC ISAs did not leave sufficient opcode space free - to include these unplanned compressed instructions, they were instead - developed as complete new ISAs. This meant compilers needed different - code generators for the separate compressed ISAs. The first compressed - RISC ISA extensions (e.g., ARM Thumb and MIPS16) used only a fixed - 16-bit instruction size, which gave good reductions in static code size - but caused an increase in dynamic instruction count, which led to lower - performance compared to the original fixed-width 32-bit instruction - size. This led to the development of a second generation of compressed - RISC ISA designs with mixed 16-bit and 32-bit instruction lengths (e.g., - ARM Thumb2, microMIPS, PowerPC VLE), so that performance was similar to - pure 32-bit instructions but with significant code size savings. - Unfortunately, these different generations of compressed ISAs are - incompatible with each other and with the original uncompressed ISA, - leading to significant complexity in documentation, implementations, and - software tools support. + Since the original RISC ISAs did not leave sufficient opcode space free + to include these unplanned compressed instructions, they were instead + developed as complete new ISAs. This meant compilers needed different + code generators for the separate compressed ISAs. The first compressed + RISC ISA extensions (e.g., ARM Thumb and MIPS16) used only a fixed + 16-bit instruction size, which gave good reductions in static code size + but caused an increase in dynamic instruction count, which led to lower + performance compared to the original fixed-width 32-bit instruction + size. This led to the development of a second generation of compressed + RISC ISA designs with mixed 16-bit and 32-bit instruction lengths (e.g., + ARM Thumb2, microMIPS, PowerPC VLE), so that performance was similar to + pure 32-bit instructions but with significant code size savings. + Unfortunately, these different generations of compressed ISAs are + incompatible with each other and with the original uncompressed ISA, + leading to significant complexity in documentation, implementations, and + software tools support. - Of the commonly used 64-bit ISAs, only PowerPC and microMIPS currently - supports a compressed instruction format. It is surprising that the most - popular 64-bit ISA for mobile platforms (ARM v8) does not include a - compressed instruction format given that static code size and dynamic - instruction fetch bandwidth are important metrics. Although static code - size is not a major concern in larger systems, instruction fetch - bandwidth can be a major bottleneck in servers running commercial - workloads, which often have a large instruction working set. + Of the commonly used 64-bit ISAs, only PowerPC and microMIPS currently + supports a compressed instruction format. It is surprising that the most + popular 64-bit ISA for mobile platforms (ARM v8) does not include a + compressed instruction format given that static code size and dynamic + instruction fetch bandwidth are important metrics. Although static code + size is not a major concern in larger systems, instruction fetch + bandwidth can be a major bottleneck in servers running commercial + workloads, which often have a large instruction working set. - Benefiting from 25 years of hindsight, RISC-V was designed to support - compressed instructions from the outset, leaving enough opcode space for - RVC to be added as a simple extension on top of the base ISA (along with - many other extensions). The philosophy of RVC is to reduce code size for - embedded applications _and_ to improve performance and energy-efficiency - for all applications due to fewer misses in the instruction cache. - Waterman shows that RVC fetches 25%-30% fewer instruction bits, which - reduces instruction cache misses by 20%-25%, or roughly the same - performance impact as doubling the instruction cache size. cite:[waterman-ms] - ==== + Benefiting from 25 years of hindsight, RISC-V was designed to support + compressed instructions from the outset, leaving enough opcode space for + RVC to be added as a simple extension on top of the base ISA (along with + many other extensions). The philosophy of RVC is to reduce code size for + embedded applications _and_ to improve performance and energy-efficiency + for all applications due to fewer misses in the instruction cache. + Waterman shows that RVC fetches 25%-30% fewer instruction bits, which + reduces instruction cache misses by 20%-25%, or roughly the same + performance impact as doubling the instruction cache size. cite:[waterman-ms] + ==== - = Compressed Instruction Formats - ((((compressed, formats)))) + = Compressed Instruction Formats + ((((compressed, formats)))) - <> shows the nine compressed instruction - formats. CR, CI, and CSS can use any of the 32 RVI registers, but CIW, - CL, CS, CA, and CB are limited to just 8 of them. - <> lists these popular registers, which - correspond to registers `x8` to `x15`. Note that there is a separate - version of load and store instructions that use the stack pointer as the - base address register, since saving to and restoring from the stack are - so prevalent, and that they use the CI and CSS formats to allow access - to all 32 data registers. CIW supplies an 8-bit immediate for the - ADDI4SPN instruction. + <> shows the nine compressed instruction + formats. CR, CI, and CSS can use any of the 32 RVI registers, but CIW, + CL, CS, CA, and CB are limited to just 8 of them. + <> lists these popular registers, which + correspond to registers `x8` to `x15`. Note that there is a separate + version of load and store instructions that use the stack pointer as the + base address register, since saving to and restoring from the stack are + so prevalent, and that they use the CI and CSS formats to allow access + to all 32 data registers. CIW supplies an 8-bit immediate for the + ADDI4SPN instruction. - [NOTE] - ==== - The RISC-V ABI was changed to make the frequently used registers map to - registers 'x8-x15'. This simplifies the decompression decoder by - having a contiguous naturally aligned set of register numbers, and is - also compatible with the RV32E and RV64E base ISAs, which only have 16 integer - registers. - ==== - Compressed register-based floating-point loads and stores also use the - CL and CS formats respectively, with the eight registers mapping to `f8` to `f15`. - ((((calling convention, standard)))) - [NOTE] - ==== - _The standard RISC-V calling convention maps the most frequently used - floating-point registers to registers `f8` to `f15`, which allows the - same register decompression decoding as for integer register numbers._ - ==== - ((((register source spcifiers, c-ext)))) - The formats were designed to keep bits for the two register source - specifiers in the same place in all instructions, while the destination - register field can move. When the full 5-bit destination register - specifier is present, it is in the same place as in the 32-bit RISC-V - encoding. Where immediates are sign-extended, the sign extension is - always from bit 12. Immediate fields have been scrambled, as in the base - specification, to reduce the number of immediate muxes required. - [NOTE] - ==== - The immediate fields are scrambled in the instruction formats instead of - in sequential order so that as many bits as possible are in the same - position in every instruction, thereby simplifying implementations. - ==== + [NOTE] + ==== + The RISC-V ABI was changed to make the frequently used registers map to + registers 'x8-x15'. This simplifies the decompression decoder by + having a contiguous naturally aligned set of register numbers, and is + also compatible with the RV32E and RV64E base ISAs, which only have 16 integer + registers. + ==== + Compressed register-based floating-point loads and stores also use the + CL and CS formats respectively, with the eight registers mapping to `f8` to `f15`. + ((((calling convention, standard)))) + [NOTE] + ==== + _The standard RISC-V calling convention maps the most frequently used + floating-point registers to registers `f8` to `f15`, which allows the + same register decompression decoding as for integer register numbers._ + ==== + ((((register source spcifiers, c-ext)))) + The formats were designed to keep bits for the two register source + specifiers in the same place in all instructions, while the destination + register field can move. When the full 5-bit destination register + specifier is present, it is in the same place as in the 32-bit RISC-V + encoding. Where immediates are sign-extended, the sign extension is + always from bit 12. Immediate fields have been scrambled, as in the base + specification, to reduce the number of immediate muxes required. + [NOTE] + ==== + The immediate fields are scrambled in the instruction formats instead of + in sequential order so that as many bits as possible are in the same + position in every instruction, thereby simplifying implementations. + ==== - For many RVC instructions, zero-valued immediates are disallowed and - `x0` is not a valid 5-bit register specifier. These restrictions free up - encoding space for other instructions requiring fewer operand bits. + For many RVC instructions, zero-valued immediates are disallowed and + `x0` is not a valid 5-bit register specifier. These restrictions free up + encoding space for other instructions requiring fewer operand bits. - //[[cr-register]] - //include::images/wavedrom/cr-register.adoc[] - //.Compressed 16-bit RVC instructions - //(((compressed, 16-bit))) + //[[cr-register]] + //include::images/wavedrom/cr-register.adoc[] + //.Compressed 16-bit RVC instructions + //(((compressed, 16-bit))) - [[rvc-form]] - .Compressed 16-bit RVC instruction formats - //[%header] - [float="center",align="center",cols="1a, 2a",frame="none",grid="none"] - |=== - | - [%autowidth,float="right",align="right",cols="^,^",frame="none",grid="none",options="noheader"] - !=== - !Format ! Meaning - !CR ! Register - !CI ! Immediate - !CSS ! Stack-relative Store - !CIW ! Wide Immediate - !CL ! Load - !CS ! Store - !CA ! Arithmetic - !CB ! Branch/Arithmetic - !CJ ! Jump - !=== - | - [float="left",align="left",cols="1,1,1,1,1,1,1",options="noheader"] - !=== - 2+^!15 14 13 12 2+^!11 10 9 8 7 2+^!6 5 4 3 2 ^!1 0 - 2+^!funct4 2+^!rd/rs1 2+^!rs2 ^! op - ^!funct3 ^!imm 2+^!rd/rs1 2+^!imm ^! op - ^!funct3 3+^!imm 2+^!rs2 ^! op - ^!funct3 4+^!imm ^!rd′ ^! op - ^!funct3 2+^!imm ^!rs1′ ^!imm ^!rd′ ^! op - ^!funct3 2+^!imm ^!rs1′ ^! imm ^!rs2′ ^! op - 3+^!funct6 ^!rd′/rs1′ ^!funct2 ^!rs2′ ^! op - ^!funct3 2+^!offset ^!rd′/rs1′ 2+^!offset ^! op - ^!funct3 5+^!jump target ^! op - !=== - |=== + [[rvc-form]] + .Compressed 16-bit RVC instruction formats + //[%header] + [float="center",align="center",cols="1a, 2a",frame="none",grid="none"] + |=== + | + [%autowidth,float="right",align="right",cols="^,^",frame="none",grid="none",options="noheader"] + !=== + !Format ! Meaning + !CR ! Register + !CI ! Immediate + !CSS ! Stack-relative Store + !CIW ! Wide Immediate + !CL ! Load + !CS ! Store + !CA ! Arithmetic + !CB ! Branch/Arithmetic + !CJ ! Jump + !=== + | + [float="left",align="left",cols="1,1,1,1,1,1,1",options="noheader"] + !=== + 2+^!15 14 13 12 2+^!11 10 9 8 7 2+^!6 5 4 3 2 ^!1 0 + 2+^!funct4 2+^!rd/rs1 2+^!rs2 ^! op + ^!funct3 ^!imm 2+^!rd/rs1 2+^!imm ^! op + ^!funct3 3+^!imm 2+^!rs2 ^! op + ^!funct3 4+^!imm ^!rd′ ^! op + ^!funct3 2+^!imm ^!rs1′ ^!imm ^!rd′ ^! op + ^!funct3 2+^!imm ^!rs1′ ^! imm ^!rs2′ ^! op + 3+^!funct6 ^!rd′/rs1′ ^!funct2 ^!rs2′ ^! op + ^!funct3 2+^!offset ^!rd′/rs1′ 2+^!offset ^! op + ^!funct3 5+^!jump target ^! op + !=== + |=== - [[registers]] - .Registers specified by the three-bit _rs1_′, _rs2_′, and _rd_′ fields of the CIW, CL, CS, CA, and CB formats. - //[cols="20%,10%,10%,10%,10%,10%,10%,10%,10%"] - [float="center",align="center",cols="1a, 1a",frame="none",grid="none"] - |=== - | - [%autowidth,cols="<",frame="none",grid="none",options="noheader"] - !=== - !RVC Register Number - !Integer Register Number - !Integer Register ABI Name - !Floating-Point Register Number - !Floating-Point Register ABI Name - !=== - | + [[registers]] + .Registers specified by the three-bit _rs1_′, _rs2_′, and _rd_′ fields of the CIW, CL, CS, CA, and CB formats. + //[cols="20%,10%,10%,10%,10%,10%,10%,10%,10%"] + [float="center",align="center",cols="1a, 1a",frame="none",grid="none"] + |=== + | + [%autowidth,cols="<",frame="none",grid="none",options="noheader"] + !=== + !RVC Register Number + !Integer Register Number + !Integer Register ABI Name + !Floating-Point Register Number + !Floating-Point Register ABI Name + !=== + | - [%autowidth,cols="^,^,^,^,^,^,^,^",options="noheader"] - !=== - !`000` !`001` !`010` !`011` !`100` !`101` !`110` !`111` - !`x8` !`x9` !`x10` !`x11` !`x12` !`x13` !`x14`!`x15` - !`s0` !`s1` !`a0` !`a1` !`a2` !`a3` !`a4`!`a5` - !`f8` !`f9` !`f10` !`f11` !`f12` !`f13`!`f14` !`f15` - !`fs0` !`fs1` !`fa0` !`fa1` !`fa2`!`fa3` !`fa4` !`fa5` - !=== - |=== - params: - MUTABLE_MISA_C: - description: | - Indicates whether or not the `C` extension can be disabled with the `misa.C` bit. - schema: - type: boolean \ No newline at end of file + [%autowidth,cols="^,^,^,^,^,^,^,^",options="noheader"] + !=== + !`000` !`001` !`010` !`011` !`100` !`101` !`110` !`111` + !`x8` !`x9` !`x10` !`x11` !`x12` !`x13` !`x14`!`x15` + !`s0` !`s1` !`a0` !`a1` !`a2` !`a3` !`a4`!`a5` + !`f8` !`f9` !`f10` !`f11` !`f12` !`f13`!`f14` !`f15` + !`fs0` !`fs1` !`fa0` !`fa1` !`fa2`!`fa3` !`fa4` !`fa5` + !=== + |=== +params: + MUTABLE_MISA_C: + description: | + Indicates whether or not the `C` extension can be disabled with the `misa.C` bit. + schema: + type: boolean \ No newline at end of file diff --git a/arch/ext/D.yaml b/arch/ext/D.yaml index d9d9021de..a5b20acf8 100644 --- a/arch/ext/D.yaml +++ b/arch/ext/D.yaml @@ -1,107 +1,109 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -D: - type: unprivileged - long_name: Double-precision floating-point - versions: - - version: "2.2.0" - state: ratified - ratification_date: 2019-12 - changes: - - Define NaN-boxing scheme, changed definition of FMAX and FMIN - implies: [F, "2.2.0"] - description: | - The `D` extension adds - double-precision floating-point computational instructions compliant - with the https://ieeexplore.ieee.org/document/4610935[IEEE 754-2008] arithmetic standard. The D extension depends on - the base single-precision instruction subset `F`. - (((double-precision, floating point))) - (((floating point, double precision))) +$schema: "ext_schema.json#" +kind: extension +name: D +type: unprivileged +long_name: Double-precision floating-point +versions: +- version: "2.2.0" + state: ratified + ratification_date: 2019-12 + changes: + - Define NaN-boxing scheme, changed definition of FMAX and FMIN + implies: [F, "2.2.0"] +description: | + The `D` extension adds + double-precision floating-point computational instructions compliant + with the https://ieeexplore.ieee.org/document/4610935[IEEE 754-2008] arithmetic standard. The D extension depends on + the base single-precision instruction subset `F`. + (((double-precision, floating point))) + (((floating point, double precision))) - = D Register State + = D Register State - The D extension widens the 32 floating-point registers, `f0-f31`, to - 64 bits (FLEN=64 in <>. The `f` registers can - now hold either 32-bit or 64-bit floating-point values as described - below in <>. + The D extension widens the 32 floating-point registers, `f0-f31`, to + 64 bits (FLEN=64 in <>. The `f` registers can + now hold either 32-bit or 64-bit floating-point values as described + below in <>. - [NOTE] - ==== - FLEN can be 32, 64, or 128 depending on which of the F, D, and Q - extensions are supported. There can be up to four different - floating-point precisions supported, including H, F, D, and Q. - ==== - (((floating-point, supported precisions))) + [NOTE] + ==== + FLEN can be 32, 64, or 128 depending on which of the F, D, and Q + extensions are supported. There can be up to four different + floating-point precisions supported, including H, F, D, and Q. + ==== + (((floating-point, supported precisions))) - [[nanboxing]] - = NaN Boxing of Narrower Values + [[nanboxing]] + = NaN Boxing of Narrower Values - When multiple floating-point precisions are supported, then valid values - of narrower _n_-bit types, _n_>. We use the term FLEN to describe the width of - the floating-point registers in the RISC-V ISA, and FLEN=32 for the F - single-precision floating-point extension. Most floating-point - instructions operate on values in the floating-point register file. - Floating-point load and store instructions transfer floating-point - values between registers and memory. Instructions to transfer values to and from the integer register file are also provided. + The F extension adds 32 floating-point registers, `f0-f31`, each 32 + bits wide, and a floating-point control and status register `fcsr`, + which contains the operating mode and exception status of the + floating-point unit. This additional state is shown in + <>. We use the term FLEN to describe the width of + the floating-point registers in the RISC-V ISA, and FLEN=32 for the F + single-precision floating-point extension. Most floating-point + instructions operate on values in the floating-point register file. + Floating-point load and store instructions transfer floating-point + values between registers and memory. Instructions to transfer values to and from the integer register file are also provided. - [TIP] - ==== - We considered a unified register file for both integer and - floating-point values as this simplifies software register allocation - and calling conventions, and reduces total user state. However, a split - organization increases the total number of registers accessible with a - given instruction width, simplifies provision of enough regfile ports - for wide superscalar issue, supports decoupled floating-point-unit - architectures, and simplifies use of internal floating-point encoding - techniques. Compiler support and calling conventions for split register - file architectures are well understood, and using dirty bits on - floating-point register file state can reduce context-switch overhead. - ==== + [TIP] + ==== + We considered a unified register file for both integer and + floating-point values as this simplifies software register allocation + and calling conventions, and reduces total user state. However, a split + organization increases the total number of registers accessible with a + given instruction width, simplifies provision of enough regfile ports + for wide superscalar issue, supports decoupled floating-point-unit + architectures, and simplifies use of internal floating-point encoding + techniques. Compiler support and calling conventions for split register + file architectures are well understood, and using dirty bits on + floating-point register file state can reduce context-switch overhead. + ==== - [[fprs]] - .RISC-V standard F extension single-precision floating-point state - [cols="<,^,>",options="header",width="50%",align="center",grid="rows"] - |=== - | [.small]#FLEN-1#| >| [.small]#0# - 3+^| [.small]#f0# - 3+^| [.small]#f1# - 3+^| [.small]#f2# - 3+^| [.small]#f3# - 3+^| [.small]#f4# - 3+^| [.small]#f5# - 3+^| [.small]#f6# - 3+^| [.small]#f7# - 3+^| [.small]#f8# - 3+^| [.small]#f9# - 3+^| [.small]#f10# - 3+^| [.small]#f11# - 3+^| [.small]#f12# - 3+^| [.small]#f13# - 3+^| [.small]#f14# - 3+^| [.small]#f15# - 3+^| [.small]#f16# - 3+^| [.small]#f17# - 3+^| [.small]#f18# - 3+^| [.small]#f19# - 3+^| [.small]#f20# - 3+^| [.small]#f21# - 3+^| [.small]#f22# - 3+^| [.small]#f23# - 3+^| [.small]#f24# - 3+^| [.small]#f25# - 3+^| [.small]#f26# - 3+^| [.small]#f27# - 3+^| [.small]#f28# - 3+^| [.small]#f29# - 3+^| [.small]#f30# - 3+^| [.small]#f31# - 3+^| [.small]#FLEN# - | [.small]#31#| >| [.small]#0# - 3+^| [.small]#fcsr# - 3+^| [.small]#32# - |=== + [[fprs]] + .RISC-V standard F extension single-precision floating-point state + [cols="<,^,>",options="header",width="50%",align="center",grid="rows"] + |=== + | [.small]#FLEN-1#| >| [.small]#0# + 3+^| [.small]#f0# + 3+^| [.small]#f1# + 3+^| [.small]#f2# + 3+^| [.small]#f3# + 3+^| [.small]#f4# + 3+^| [.small]#f5# + 3+^| [.small]#f6# + 3+^| [.small]#f7# + 3+^| [.small]#f8# + 3+^| [.small]#f9# + 3+^| [.small]#f10# + 3+^| [.small]#f11# + 3+^| [.small]#f12# + 3+^| [.small]#f13# + 3+^| [.small]#f14# + 3+^| [.small]#f15# + 3+^| [.small]#f16# + 3+^| [.small]#f17# + 3+^| [.small]#f18# + 3+^| [.small]#f19# + 3+^| [.small]#f20# + 3+^| [.small]#f21# + 3+^| [.small]#f22# + 3+^| [.small]#f23# + 3+^| [.small]#f24# + 3+^| [.small]#f25# + 3+^| [.small]#f26# + 3+^| [.small]#f27# + 3+^| [.small]#f28# + 3+^| [.small]#f29# + 3+^| [.small]#f30# + 3+^| [.small]#f31# + 3+^| [.small]#FLEN# + | [.small]#31#| >| [.small]#0# + 3+^| [.small]#fcsr# + 3+^| [.small]#32# + |=== - == Floating-Point Control and Status Register + == Floating-Point Control and Status Register - The floating-point control and status register, `fcsr`, is a RISC-V - control and status register (CSR). It is a 32-bit read/write register - that selects the dynamic rounding mode for floating-point arithmetic - operations and holds the accrued exception flags, as shown in <>. + The floating-point control and status register, `fcsr`, is a RISC-V + control and status register (CSR). It is a 32-bit read/write register + that selects the dynamic rounding mode for floating-point arithmetic + operations and holds the accrued exception flags, as shown in <>. - [[fcsr, Floating-Point Control and Status Register]] - .Floating-point control and status register - include::images/wavedrom/float-csr.adoc[] + [[fcsr, Floating-Point Control and Status Register]] + .Floating-point control and status register + include::images/wavedrom/float-csr.adoc[] - The `fcsr` register can be read and written with the FRCSR and FSCSR - instructions, which are assembler pseudoinstructions built on the - underlying CSR access instructions. FRCSR reads `fcsr` by copying it - into integer register _rd_. FSCSR swaps the value in `fcsr` by copying - the original value into integer register _rd_, and then writing a new - value obtained from integer register _rs1_ into `fcsr`. + The `fcsr` register can be read and written with the FRCSR and FSCSR + instructions, which are assembler pseudoinstructions built on the + underlying CSR access instructions. FRCSR reads `fcsr` by copying it + into integer register _rd_. FSCSR swaps the value in `fcsr` by copying + the original value into integer register _rd_, and then writing a new + value obtained from integer register _rs1_ into `fcsr`. - The fields within the `fcsr` can also be accessed individually through - different CSR addresses, and separate assembler pseudoinstructions are defined - for these accesses. The FRRM instruction reads the Rounding Mode field `frm` - (`fcsr` bits 7--5) and copies it into the least-significant three bits of - integer register _rd_, with zero in all other bits. FSRM swaps the value in - `frm` by copying the original value into integer register _rd_, and then - writing a new value obtained from the three least-significant bits of integer - register _rs1_ into `frm`. FRFLAGS and FSFLAGS are defined analogously for the - Accrued Exception Flags field `fflags` (`fcsr` bits 4--0). + The fields within the `fcsr` can also be accessed individually through + different CSR addresses, and separate assembler pseudoinstructions are defined + for these accesses. The FRRM instruction reads the Rounding Mode field `frm` + (`fcsr` bits 7--5) and copies it into the least-significant three bits of + integer register _rd_, with zero in all other bits. FSRM swaps the value in + `frm` by copying the original value into integer register _rd_, and then + writing a new value obtained from the three least-significant bits of integer + register _rs1_ into `frm`. FRFLAGS and FSFLAGS are defined analogously for the + Accrued Exception Flags field `fflags` (`fcsr` bits 4--0). - Bits 31--8 of the `fcsr` are reserved for other standard extensions. If - these extensions are not present, implementations shall ignore writes to - these bits and supply a zero value when read. Standard software should - preserve the contents of these bits. + Bits 31--8 of the `fcsr` are reserved for other standard extensions. If + these extensions are not present, implementations shall ignore writes to + these bits and supply a zero value when read. Standard software should + preserve the contents of these bits. - Floating-point operations use either a static rounding mode encoded in - the instruction, or a dynamic rounding mode held in `frm`. Rounding - modes are encoded as shown in <>. A value of 111 in the - instruction's _rm_ field selects the dynamic rounding mode held in - `frm`. The behavior of floating-point instructions that depend on - rounding mode when executed with a reserved rounding mode is _reserved_, including both static reserved rounding modes (101-110) and dynamic reserved rounding modes (101-111). Some instructions, including widening conversions, have the _rm_ field but are nevertheless mathematically unaffected by the rounding mode; software should set their _rm_ field to - RNE (000) but implementations must treat the _rm_ field as usual (in - particular, with regard to decoding legal vs. reserved encodings). + Floating-point operations use either a static rounding mode encoded in + the instruction, or a dynamic rounding mode held in `frm`. Rounding + modes are encoded as shown in <>. A value of 111 in the + instruction's _rm_ field selects the dynamic rounding mode held in + `frm`. The behavior of floating-point instructions that depend on + rounding mode when executed with a reserved rounding mode is _reserved_, including both static reserved rounding modes (101-110) and dynamic reserved rounding modes (101-111). Some instructions, including widening conversions, have the _rm_ field but are nevertheless mathematically unaffected by the rounding mode; software should set their _rm_ field to + RNE (000) but implementations must treat the _rm_ field as usual (in + particular, with regard to decoding legal vs. reserved encodings). - [[rm]] - .Rounding mode encoding. - [%autowidth,float="center",align="center",cols="^,^,<",options="header"] - |=== - |Rounding Mode |Mnemonic |Meaning - |000 |RNE |Round to Nearest, ties to Even - |001 |RTZ |Round towards Zero - |010 |RDN |Round Down (towards latexmath:[$-\infty$]) - |011 |RUP |Round Up (towards latexmath:[$+\infty$]) - |100 |RMM |Round to Nearest, ties to Max Magnitude - |101 | |_Reserved for future use._ - |110 | |_Reserved for future use._ - |111 |DYN |In instruction's _rm_ field, selects dynamic rounding mode; In Rounding Mode register, _reserved_. - |=== + [[rm]] + .Rounding mode encoding. + [%autowidth,float="center",align="center",cols="^,^,<",options="header"] + |=== + |Rounding Mode |Mnemonic |Meaning + |000 |RNE |Round to Nearest, ties to Even + |001 |RTZ |Round towards Zero + |010 |RDN |Round Down (towards latexmath:[$-\infty$]) + |011 |RUP |Round Up (towards latexmath:[$+\infty$]) + |100 |RMM |Round to Nearest, ties to Max Magnitude + |101 | |_Reserved for future use._ + |110 | |_Reserved for future use._ + |111 |DYN |In instruction's _rm_ field, selects dynamic rounding mode; In Rounding Mode register, _reserved_. + |=== - [NOTE] - ==== - The C99 language standard effectively mandates the provision of a - dynamic rounding mode register. In typical implementations, writes to - the dynamic rounding mode CSR state will serialize the pipeline. Static - rounding modes are used to implement specialized arithmetic operations - that often have to switch frequently between different rounding modes. + [NOTE] + ==== + The C99 language standard effectively mandates the provision of a + dynamic rounding mode register. In typical implementations, writes to + the dynamic rounding mode CSR state will serialize the pipeline. Static + rounding modes are used to implement specialized arithmetic operations + that often have to switch frequently between different rounding modes. - The ratified version of the F spec mandated that an illegal-instruction - exception was raised when an instruction was executed with a reserved - dynamic rounding mode. This has been weakened to reserved, which matches - the behavior of static rounding-mode instructions. Raising an - illegal-instruction exception is still valid behavior when encountering a - reserved encoding, so implementations compatible with the ratified spec - are compatible with the weakened spec. - ==== + The ratified version of the F spec mandated that an illegal-instruction + exception was raised when an instruction was executed with a reserved + dynamic rounding mode. This has been weakened to reserved, which matches + the behavior of static rounding-mode instructions. Raising an + illegal-instruction exception is still valid behavior when encountering a + reserved encoding, so implementations compatible with the ratified spec + are compatible with the weakened spec. + ==== - The accrued exception flags indicate the exception conditions that have - arisen on any floating-point arithmetic instruction since the field was - last reset by software, as shown in <>. The base - RISC-V ISA does not support generating a trap on the setting of a - floating-point exception flag. - (((floating-point, exception flag))) + The accrued exception flags indicate the exception conditions that have + arisen on any floating-point arithmetic instruction since the field was + last reset by software, as shown in <>. The base + RISC-V ISA does not support generating a trap on the setting of a + floating-point exception flag. + (((floating-point, exception flag))) - [[bitdef]] - .Accrued exception flag encoding. - [%autowidth,float="center",align="center",cols="^,<",options="header",] - |=== - |Flag Mnemonic |Flag Meaning - |NV |Invalid Operation - |DZ |Divide by Zero - |OF |Overflow - |UF |Underflow - |NX |Inexact - |=== + [[bitdef]] + .Accrued exception flag encoding. + [%autowidth,float="center",align="center",cols="^,<",options="header",] + |=== + |Flag Mnemonic |Flag Meaning + |NV |Invalid Operation + |DZ |Divide by Zero + |OF |Overflow + |UF |Underflow + |NX |Inexact + |=== - [NOTE] - ==== - As allowed by the standard, we do not support traps on floating-point - exceptions in the F extension, but instead require explicit checks of - the flags in software. We considered adding branches controlled directly - by the contents of the floating-point accrued exception flags, but - ultimately chose to omit these instructions to keep the ISA simple. - ==== + [NOTE] + ==== + As allowed by the standard, we do not support traps on floating-point + exceptions in the F extension, but instead require explicit checks of + the flags in software. We considered adding branches controlled directly + by the contents of the floating-point accrued exception flags, but + ultimately chose to omit these instructions to keep the ISA simple. + ==== - = NaN Generation and Propagation + = NaN Generation and Propagation - Except when otherwise stated, if the result of a floating-point - operation is NaN, it is the canonical NaN. The canonical NaN has a - positive sign and all significand bits clear except the MSB, a.k.a. the - quiet bit. For single-precision floating-point, this corresponds to the pattern `0x7fc00000`. - (((NaN, generation))) - (((NaN, propagation))) + Except when otherwise stated, if the result of a floating-point + operation is NaN, it is the canonical NaN. The canonical NaN has a + positive sign and all significand bits clear except the MSB, a.k.a. the + quiet bit. For single-precision floating-point, this corresponds to the pattern `0x7fc00000`. + (((NaN, generation))) + (((NaN, propagation))) - [TIP] - ==== - We considered propagating NaN payloads, as is recommended by the - standard, but this decision would have increased hardware cost. - Moreover, since this feature is optional in the standard, it cannot be - used in portable code. + [TIP] + ==== + We considered propagating NaN payloads, as is recommended by the + standard, but this decision would have increased hardware cost. + Moreover, since this feature is optional in the standard, it cannot be + used in portable code. - Implementors are free to provide a NaN payload propagation scheme as a - nonstandard extension enabled by a nonstandard operating mode. However, the canonical NaN scheme described above must always be supported and should be the default mode. - ==== - ''' - [NOTE] - ==== - We require implementations to return the standard-mandated default - values in the case of exceptional conditions, without any further - intervention on the part of user-level software (unlike the Alpha ISA - floating-point trap barriers). We believe full hardware handling of - exceptional cases will become more common, and so wish to avoid - complicating the user-level ISA to optimize other approaches. - Implementations can always trap to machine-mode software handlers to - provide exceptional default values. - ==== + Implementors are free to provide a NaN payload propagation scheme as a + nonstandard extension enabled by a nonstandard operating mode. However, the canonical NaN scheme described above must always be supported and should be the default mode. + ==== + ''' + [NOTE] + ==== + We require implementations to return the standard-mandated default + values in the case of exceptional conditions, without any further + intervention on the part of user-level software (unlike the Alpha ISA + floating-point trap barriers). We believe full hardware handling of + exceptional cases will become more common, and so wish to avoid + complicating the user-level ISA to optimize other approaches. + Implementations can always trap to machine-mode software handlers to + provide exceptional default values. + ==== - = Subnormal Arithmetic + = Subnormal Arithmetic - Operations on subnormal numbers are handled in accordance with the IEEE 754-2008 standard. - (((operations, subnormal))) + Operations on subnormal numbers are handled in accordance with the IEEE 754-2008 standard. + (((operations, subnormal))) - In the parlance of the IEEE standard, tininess is detected after - rounding. - (((tininess, handling))) + In the parlance of the IEEE standard, tininess is detected after + rounding. + (((tininess, handling))) - [NOTE] - ==== - Detecting tininess after rounding results in fewer spurious underflow - signals. - ==== - params: - MUTABLE_MISA_F: - description: | - Indicates whether or not the `F` extension can be disabled with the `misa.F` bit. - schema: - type: boolean - HW_MSTATUS_FS_DIRTY_UPDATE: - description: | - Indicates whether or not hardware will write to `mstatus.FS` + [NOTE] + ==== + Detecting tininess after rounding results in fewer spurious underflow + signals. + ==== +params: + MUTABLE_MISA_F: + description: | + Indicates whether or not the `F` extension can be disabled with the `misa.F` bit. + schema: + type: boolean + HW_MSTATUS_FS_DIRTY_UPDATE: + description: | + Indicates whether or not hardware will write to `mstatus.FS` - Values are: - [separator="!"] - !=== - h! never ! Hardware never writes `mstatus.FS` - h! precise ! Hardware writes `mstatus.FS` to the Dirty (3) state precisely when F registers are modified - h! imprecise ! Hardware writes `mstatus.FS` imprecisely. This will result in a call to unpredictable() on any attempt to read `mstatus` or write FP state. - !=== - schema: - type: string - enum: ["never", "precise", "imprecise"] - MSTATUS_FS_LEGAL_VALUES: - description: | - The set of values that mstatus.FS will accept from a software write. - schema: - type: array - items: - type: integer - enum: [0,1,2,3] - maxItems: 4 - uniqueItems: true - also_defined_in: S - extra_validation: | - assert MSTATUS_FS_LEGAL_VALUES.include?(0) && MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F) + Values are: + [separator="!"] + !=== + h! never ! Hardware never writes `mstatus.FS` + h! precise ! Hardware writes `mstatus.FS` to the Dirty (3) state precisely when F registers are modified + h! imprecise ! Hardware writes `mstatus.FS` imprecisely. This will result in a call to unpredictable() on any attempt to read `mstatus` or write FP state. + !=== + schema: + type: string + enum: ["never", "precise", "imprecise"] + MSTATUS_FS_LEGAL_VALUES: + description: | + The set of values that mstatus.FS will accept from a software write. + schema: + type: array + items: + type: integer + enum: [0,1,2,3] + maxItems: 4 + uniqueItems: true + also_defined_in: S + extra_validation: | + assert MSTATUS_FS_LEGAL_VALUES.include?(0) && MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F) - # if HW is writing FS, then Dirty (3) better be a supported value - assert MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F) && (HW_MSTATUS_FS_DIRTY_UPDATE != "never") \ No newline at end of file + # if HW is writing FS, then Dirty (3) better be a supported value + assert MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F) && (HW_MSTATUS_FS_DIRTY_UPDATE != "never") \ No newline at end of file diff --git a/arch/ext/H.yaml b/arch/ext/H.yaml index dd8270b5b..0e8bb8bcd 100644 --- a/arch/ext/H.yaml +++ b/arch/ext/H.yaml @@ -1,637 +1,639 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -H: - type: privileged - long_name: Hypervisor - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2019-12 - requires: - name: S - version: '>= 1.12.0' - interrupt_codes: - - num: 2 - name: Virtual supervisor software interrupt - var: VirtualSupervisorSoftware - - num: 6 - name: Virtual supervisor timer interrupt - var: VirtualSupervisorTimer - - num: 10 - name: Virtual supervisor external interrupt - var: VirtualSupervisorExternal - - num: 12 - name: Supervisor guest external interrupt - var: SupervisorGuestExternal - exception_codes: - - num: 10 - name: Environment call from VS-mode - var: VScall - - num: 20 - name: Instruction guest page fault - var: InstructionGuestPageFault - - num: 21 - name: Load guest page fault - var: LoadGuestPageFault - - num: 22 - name: Virtual instruction - var: VirtualInstruction - - num: 23 - name: Store/AMO guest page fault - var: StoreAmoGuestPageFault - description: | - This chapter describes the RISC-V hypervisor extension, which - virtualizes the supervisor-level architecture to support the efficient - hosting of guest operating systems atop a type-1 or type-2 hypervisor. - The hypervisor extension changes supervisor mode into - _hypervisor-extended supervisor mode_ (HS-mode, or _hypervisor mode_ for - short), where a hypervisor or a hosting-capable operating system runs. - The hypervisor extension also adds another stage of address translation, - from _guest physical addresses_ to supervisor physical addresses, to - virtualize the memory and memory-mapped I/O subsystems for a guest - operating system. HS-mode acts the same as S-mode, but with additional - instructions and CSRs that control the new stage of address translation - and support hosting a guest OS in virtual S-mode (VS-mode). Regular - S-mode operating systems can execute without modification either in - HS-mode or as VS-mode guests. - - In HS-mode, an OS or hypervisor interacts with the machine through the - same SBI as an OS normally does from S-mode. An HS-mode hypervisor is - expected to implement the SBI for its VS-mode guest. - - The hypervisor extension depends on an "I" base integer ISA with 32 - `x` registers (RV32I or RV64I), not RV32E or RV64E, which have only 16 `x` - registers. CSR `mtval` must not be read-only zero, and standard - page-based address translation must be supported, either Sv32 for RV32, - or a minimum of Sv39 for RV64. - - The hypervisor extension is enabled by setting bit 7 in the `misa` CSR, - which corresponds to the letter H. RISC-V harts that implement the - hypervisor extension are encouraged not to hardwire `misa`[7], so that - the extension may be disabled. - - [NOTE] - ==== - The baseline privileged architecture is designed to simplify the use of - classic virtualization techniques, where a guest OS is run at - user-level, as the few privileged instructions can be easily detected - and trapped. The hypervisor extension improves virtualization - performance by reducing the frequency of these traps. - - The hypervisor extension has been designed to be efficiently emulable on - platforms that do not implement the extension, by running the hypervisor - in S-mode and trapping into M-mode for hypervisor CSR accesses and to - maintain shadow page tables. The majority of CSR accesses for type-2 - hypervisors are valid S-mode accesses so need not be trapped. - Hypervisors can support nested virtualization analogously. - ==== - - = Privilege Modes - - The current _virtualization mode_, denoted V, indicates whether the hart - is currently executing in a guest. When V=1, the hart is either in - virtual S-mode (VS-mode), or in virtual U-mode (VU-mode) atop a guest OS - running in VS-mode. When V=0, the hart is either in M-mode, in HS-mode, - or in U-mode atop an OS running in HS-mode. The virtualization mode also - indicates whether two-stage address translation is active (V=1) or - inactive (V=0). <> lists the - possible privilege modes of a RISC-V hart with the hypervisor extension. - - <<< - - [[HPrivModes]] - .Privilege modes with the hypervisor extension. - [float="center",align="center",cols="~,~,~,~,~"] - |=== - ^|Virtualization + - Mode (V) ^|Nominal Privilege |Abbreviation |Name |Two-Stage Translation - - ^|0 + - 0 + - 0 - ^| U + - S + - M - |U-mode + - HS-mode + - M-mode - |User mode + - Hypervisor-extended supervisor mode + - Machine mode - |Off + - Off + - Off - ^|1 + - 1 - ^|U + - S - |VU-mode + - VS-mode - |Virtual user mode + - Virtual supervisor mode - |On + - On - |=== - - For privilege modes U and VU, the _nominal privilege mode_ is U, and for - privilege modes HS and VS, the nominal privilege mode is S. - - HS-mode is more privileged than VS-mode, and VS-mode is more privileged - than VU-mode. VS-mode interrupts are globally disabled when executing in - U-mode. - - [NOTE] - ==== - This description does not consider the possibility of U-mode or VU-mode - interrupts and will be revised if an extension for user-level interrupts - is adopted. - ==== - params: - MUTABLE_MISA_H: - description: | - Indicates whether or not the `H` extension can be disabled with the `misa.H` bit. - schema: +$schema: "ext_schema.json#" +kind: extension +name: H +type: privileged +long_name: Hypervisor +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2019-12 + requires: + name: S + version: '>= 1.12.0' +interrupt_codes: +- num: 2 + name: Virtual supervisor software interrupt + var: VirtualSupervisorSoftware +- num: 6 + name: Virtual supervisor timer interrupt + var: VirtualSupervisorTimer +- num: 10 + name: Virtual supervisor external interrupt + var: VirtualSupervisorExternal +- num: 12 + name: Supervisor guest external interrupt + var: SupervisorGuestExternal +exception_codes: +- num: 10 + name: Environment call from VS-mode + var: VScall +- num: 20 + name: Instruction guest page fault + var: InstructionGuestPageFault +- num: 21 + name: Load guest page fault + var: LoadGuestPageFault +- num: 22 + name: Virtual instruction + var: VirtualInstruction +- num: 23 + name: Store/AMO guest page fault + var: StoreAmoGuestPageFault +description: | + This chapter describes the RISC-V hypervisor extension, which + virtualizes the supervisor-level architecture to support the efficient + hosting of guest operating systems atop a type-1 or type-2 hypervisor. + The hypervisor extension changes supervisor mode into + _hypervisor-extended supervisor mode_ (HS-mode, or _hypervisor mode_ for + short), where a hypervisor or a hosting-capable operating system runs. + The hypervisor extension also adds another stage of address translation, + from _guest physical addresses_ to supervisor physical addresses, to + virtualize the memory and memory-mapped I/O subsystems for a guest + operating system. HS-mode acts the same as S-mode, but with additional + instructions and CSRs that control the new stage of address translation + and support hosting a guest OS in virtual S-mode (VS-mode). Regular + S-mode operating systems can execute without modification either in + HS-mode or as VS-mode guests. + + In HS-mode, an OS or hypervisor interacts with the machine through the + same SBI as an OS normally does from S-mode. An HS-mode hypervisor is + expected to implement the SBI for its VS-mode guest. + + The hypervisor extension depends on an "I" base integer ISA with 32 + `x` registers (RV32I or RV64I), not RV32E or RV64E, which have only 16 `x` + registers. CSR `mtval` must not be read-only zero, and standard + page-based address translation must be supported, either Sv32 for RV32, + or a minimum of Sv39 for RV64. + + The hypervisor extension is enabled by setting bit 7 in the `misa` CSR, + which corresponds to the letter H. RISC-V harts that implement the + hypervisor extension are encouraged not to hardwire `misa`[7], so that + the extension may be disabled. + + [NOTE] + ==== + The baseline privileged architecture is designed to simplify the use of + classic virtualization techniques, where a guest OS is run at + user-level, as the few privileged instructions can be easily detected + and trapped. The hypervisor extension improves virtualization + performance by reducing the frequency of these traps. + + The hypervisor extension has been designed to be efficiently emulable on + platforms that do not implement the extension, by running the hypervisor + in S-mode and trapping into M-mode for hypervisor CSR accesses and to + maintain shadow page tables. The majority of CSR accesses for type-2 + hypervisors are valid S-mode accesses so need not be trapped. + Hypervisors can support nested virtualization analogously. + ==== + + = Privilege Modes + + The current _virtualization mode_, denoted V, indicates whether the hart + is currently executing in a guest. When V=1, the hart is either in + virtual S-mode (VS-mode), or in virtual U-mode (VU-mode) atop a guest OS + running in VS-mode. When V=0, the hart is either in M-mode, in HS-mode, + or in U-mode atop an OS running in HS-mode. The virtualization mode also + indicates whether two-stage address translation is active (V=1) or + inactive (V=0). <> lists the + possible privilege modes of a RISC-V hart with the hypervisor extension. + + <<< + + [[HPrivModes]] + .Privilege modes with the hypervisor extension. + [float="center",align="center",cols="~,~,~,~,~"] + |=== + ^|Virtualization + + Mode (V) ^|Nominal Privilege |Abbreviation |Name |Two-Stage Translation + + ^|0 + + 0 + + 0 + ^| U + + S + + M + |U-mode + + HS-mode + + M-mode + |User mode + + Hypervisor-extended supervisor mode + + Machine mode + |Off + + Off + + Off + ^|1 + + 1 + ^|U + + S + |VU-mode + + VS-mode + |Virtual user mode + + Virtual supervisor mode + |On + + On + |=== + + For privilege modes U and VU, the _nominal privilege mode_ is U, and for + privilege modes HS and VS, the nominal privilege mode is S. + + HS-mode is more privileged than VS-mode, and VS-mode is more privileged + than VU-mode. VS-mode interrupts are globally disabled when executing in + U-mode. + + [NOTE] + ==== + This description does not consider the possibility of U-mode or VU-mode + interrupts and will be revised if an extension for user-level interrupts + is adopted. + ==== +params: + MUTABLE_MISA_H: + description: | + Indicates whether or not the `H` extension can be disabled with the `misa.H` bit. + schema: + type: boolean + extra_validation: | + # If S mode can be disabled, then H mode must also be disabled since you can't + # be in H mode without S mode + assert MUTABLE_MISA_H if MUTABLE_MISA_S + NUM_EXTERNAL_GUEST_INTERRUPTS: + description: | + Number of supported virtualized guest interrupts + + Corresponds to the `GEILEN` parameter in the RVI specs + schema: + type: integer + minimum: 1 + maximum: 63 + VS_MODE_ENDIANESS: + description: | + Endianess of data in VS-mode. Can be one of: + + * little: M-mode data is always little endian + * big: M-mode data is always big endian + * dynamic: M-mode data can be either little or big endian, + depending on the CSR field `hstatus.VSBE` + schema: + type: string + enum: [little, big, dynamic] + VU_MODE_ENDIANESS: + description: | + Endianess of data in VU-mode. Can be one of: + + * little: M-mode data is always little endian + * big: M-mode data is always big endian + * dynamic: M-mode data can be either little or big endian, + depending on the CSR field `vsstatus.UBE` + schema: + type: string + enum: [little, big, dynamic] + VUXLEN: + description: | + Set of XLENs supported in VU-mode. Can be one of: + + * 32: VUXLEN is always 32 + * 64: VUXLEN is always 64 + * 3264: VUXLEN can be changed (via `vsstatus.UXL`) between 32 and 64 + schema: + type: integer + enum: [32, 64, 3264] + extra_validation: | + assert VUXLEN == 32 if XLEN == 32 + assert (SXLEN != 32) if VUXLEN != 32 + assert (VSXLEN != 32) if VUXLEN != 32 + VSXLEN: + description: | + Set of XLENs supported in VS-mode. Can be one of: + + * 32: VSXLEN is always 32 + * 64: VSXLEN is always 64 + * 3264: VSXLEN can be changed (via `hstatus.VSXL`) between 32 and 64 + schema: + type: integer + enum: [32, 64, 3264] + extra_validation: | + assert VSXLEN == 32 if XLEN == 32 + assert (SXLEN != 32) if VSXLEN != 32 + REPORT_VA_IN_VSTVAL_ON_BREAKPOINT: + description: | + When true, `vstval` is written with the virtual PC of the EBREAK instruction (same information as `mepc`). + + When false, `vstval` is written with 0 on an EBREAK instruction. + + Regardless, `vstval` is always written with a virtual PC when an external breakpoint is generated + schema: + type: boolean + REPORT_VA_IN_VSTVAL_ON_LOAD_MISALIGNED: + description: | + When true, `vstval` is written with the virtual address of a load instruction when the + address is misaligned and MISALIGNED_LDST is false. + + When false, `vstval` is written with 0 when a load address is misaligned and + MISALIGNED_LDST is false. + schema: + type: boolean + REPORT_VA_IN_VSTVAL_ON_STORE_AMO_MISALIGNED: + description: | + When true, `vstval` is written with the virtual address of a store instruction when the + address is misaligned and MISALIGNED_LDST is false. + + When false, `vstval` is written with 0 when a store address is misaligned and + MISALIGNED_LDST is false. + schema: + type: boolean + REPORT_VA_IN_VSTVAL_ON_INSTRUCTION_MISALIGNED: + description: | + When true, `vstval` is written with the virtual PC when an instruction fetch is misaligned. + + When false, `vstval` is written with 0 when an instruction fetch is misaligned. + + Note that when IALIGN=16 (i.e., when the `C` or one of the `Zc*` extensions are implemented), + it is impossible to generate a misaligned fetch, and so this parameter has no effect. + schema: + type: boolean + REPORT_VA_IN_VSTVAL_ON_LOAD_ACCESS_FAULT: + description: | + When true, `vstval` is written with the virtual address of a load when it causes a + `LoadAccessFault`. + + WHen false, `vstval` is written with 0 when a load causes a `LoadAccessFault`. + schema: + type: boolean + REPORT_VA_IN_VSTVAL_ON_STORE_AMO_ACCESS_FAULT: + description: | + When true, `vstval` is written with the virtual address of a store when it causes a + `StoreAmoAccessFault`. + + WHen false, `vstval` is written with 0 when a store causes a `StoreAmoAccessFault`. + schema: + type: boolean + REPORT_VA_IN_VSTVAL_ON_INSTRUCTION_ACCESS_FAULT: + description: | + When true, `vstval` is written with the virtual PC of an instructino when fetch causes an + `InstructionAccessFault`. + + WHen false, `vstval` is written with 0 when an instruction fetch causes an + `InstructionAccessFault`. + schema: + type: boolean + REPORT_VA_IN_VSTVAL_ON_LOAD_PAGE_FAULT: + description: | + When true, `vstval` is written with the virtual address of a load when it causes a + `LoadPageFault`. + + WHen false, `vstval` is written with 0 when a load causes a `LoadPageFault`. + schema: + type: boolean + REPORT_VA_IN_VSTVAL_ON_STORE_AMO_PAGE_FAULT: + description: | + When true, `vstval` is written with the virtual address of a store when it causes a + `StoreAmoPageFault`. + + WHen false, `vstval` is written with 0 when a store causes a `StoreAmoPageFault`. + schema: + type: boolean + REPORT_VA_IN_VSTVAL_ON_INSTRUCTION_PAGE_FAULT: + description: | + When true, `vstval` is written with the virtual PC of an instructino when fetch causes an + `InstructionPageFault`. + + WHen false, `vstval` is written with 0 when an instruction fetch causes an + `InstructionPageFault`. + schema: + type: boolean + REPORT_ENCODING_IN_VSTVAL_ON_ILLEGAL_INSTRUCTION: + description: | + When true, `vstval` is written with the encoding of an instruction that causes an + `IllegalInstruction` exception. + + When false `vstval` is written with 0 when an `IllegalInstruction` exception occurs. + schema: + type: boolean + HCOUNTENABLE_EN: + description: | + Indicates which counters can delegated via `hcounteren` + + An unimplemented counter cannot be specified, i.e., if + HPM_COUNTER_EN[3] is false, it would be illegal to set + HCOUNTENABLE_EN[3] to true. + + HCOUNTENABLE_EN[0:2] must all be false if `Zicntr` is not implemented. + HCOUNTENABLE_EN[3:31] must all be false if `Zihpm` is not implemented. + schema: + type: array + items: type: boolean - extra_validation: | - # If S mode can be disabled, then H mode must also be disabled since you can't - # be in H mode without S mode - assert MUTABLE_MISA_H if MUTABLE_MISA_S - NUM_EXTERNAL_GUEST_INTERRUPTS: - description: | - Number of supported virtualized guest interrupts - - Corresponds to the `GEILEN` parameter in the RVI specs - schema: - type: integer - minimum: 1 - maximum: 63 - VS_MODE_ENDIANESS: - description: | - Endianess of data in VS-mode. Can be one of: - - * little: M-mode data is always little endian - * big: M-mode data is always big endian - * dynamic: M-mode data can be either little or big endian, - depending on the CSR field `hstatus.VSBE` - schema: - type: string - enum: [little, big, dynamic] - VU_MODE_ENDIANESS: - description: | - Endianess of data in VU-mode. Can be one of: - - * little: M-mode data is always little endian - * big: M-mode data is always big endian - * dynamic: M-mode data can be either little or big endian, - depending on the CSR field `vsstatus.UBE` - schema: - type: string - enum: [little, big, dynamic] - VUXLEN: - description: | - Set of XLENs supported in VU-mode. Can be one of: - - * 32: VUXLEN is always 32 - * 64: VUXLEN is always 64 - * 3264: VUXLEN can be changed (via `vsstatus.UXL`) between 32 and 64 - schema: - type: integer - enum: [32, 64, 3264] - extra_validation: | - assert VUXLEN == 32 if XLEN == 32 - assert (SXLEN != 32) if VUXLEN != 32 - assert (VSXLEN != 32) if VUXLEN != 32 - VSXLEN: - description: | - Set of XLENs supported in VS-mode. Can be one of: - - * 32: VSXLEN is always 32 - * 64: VSXLEN is always 64 - * 3264: VSXLEN can be changed (via `hstatus.VSXL`) between 32 and 64 - schema: - type: integer - enum: [32, 64, 3264] - extra_validation: | - assert VSXLEN == 32 if XLEN == 32 - assert (SXLEN != 32) if VSXLEN != 32 - REPORT_VA_IN_VSTVAL_ON_BREAKPOINT: - description: | - When true, `vstval` is written with the virtual PC of the EBREAK instruction (same information as `mepc`). - - When false, `vstval` is written with 0 on an EBREAK instruction. - - Regardless, `vstval` is always written with a virtual PC when an external breakpoint is generated - schema: - type: boolean - REPORT_VA_IN_VSTVAL_ON_LOAD_MISALIGNED: - description: | - When true, `vstval` is written with the virtual address of a load instruction when the - address is misaligned and MISALIGNED_LDST is false. - - When false, `vstval` is written with 0 when a load address is misaligned and - MISALIGNED_LDST is false. - schema: - type: boolean - REPORT_VA_IN_VSTVAL_ON_STORE_AMO_MISALIGNED: - description: | - When true, `vstval` is written with the virtual address of a store instruction when the - address is misaligned and MISALIGNED_LDST is false. - - When false, `vstval` is written with 0 when a store address is misaligned and - MISALIGNED_LDST is false. - schema: - type: boolean - REPORT_VA_IN_VSTVAL_ON_INSTRUCTION_MISALIGNED: - description: | - When true, `vstval` is written with the virtual PC when an instruction fetch is misaligned. - - When false, `vstval` is written with 0 when an instruction fetch is misaligned. - - Note that when IALIGN=16 (i.e., when the `C` or one of the `Zc*` extensions are implemented), - it is impossible to generate a misaligned fetch, and so this parameter has no effect. - schema: - type: boolean - REPORT_VA_IN_VSTVAL_ON_LOAD_ACCESS_FAULT: - description: | - When true, `vstval` is written with the virtual address of a load when it causes a - `LoadAccessFault`. - - WHen false, `vstval` is written with 0 when a load causes a `LoadAccessFault`. - schema: - type: boolean - REPORT_VA_IN_VSTVAL_ON_STORE_AMO_ACCESS_FAULT: - description: | - When true, `vstval` is written with the virtual address of a store when it causes a - `StoreAmoAccessFault`. - - WHen false, `vstval` is written with 0 when a store causes a `StoreAmoAccessFault`. - schema: - type: boolean - REPORT_VA_IN_VSTVAL_ON_INSTRUCTION_ACCESS_FAULT: - description: | - When true, `vstval` is written with the virtual PC of an instructino when fetch causes an - `InstructionAccessFault`. - - WHen false, `vstval` is written with 0 when an instruction fetch causes an - `InstructionAccessFault`. - schema: - type: boolean - REPORT_VA_IN_VSTVAL_ON_LOAD_PAGE_FAULT: - description: | - When true, `vstval` is written with the virtual address of a load when it causes a - `LoadPageFault`. - - WHen false, `vstval` is written with 0 when a load causes a `LoadPageFault`. - schema: - type: boolean - REPORT_VA_IN_VSTVAL_ON_STORE_AMO_PAGE_FAULT: - description: | - When true, `vstval` is written with the virtual address of a store when it causes a - `StoreAmoPageFault`. - - WHen false, `vstval` is written with 0 when a store causes a `StoreAmoPageFault`. - schema: - type: boolean - REPORT_VA_IN_VSTVAL_ON_INSTRUCTION_PAGE_FAULT: - description: | - When true, `vstval` is written with the virtual PC of an instructino when fetch causes an - `InstructionPageFault`. - - WHen false, `vstval` is written with 0 when an instruction fetch causes an - `InstructionPageFault`. - schema: - type: boolean - REPORT_ENCODING_IN_VSTVAL_ON_ILLEGAL_INSTRUCTION: - description: | - When true, `vstval` is written with the encoding of an instruction that causes an - `IllegalInstruction` exception. - - When false `vstval` is written with 0 when an `IllegalInstruction` exception occurs. - schema: - type: boolean - HCOUNTENABLE_EN: - description: | - Indicates which counters can delegated via `hcounteren` - - An unimplemented counter cannot be specified, i.e., if - HPM_COUNTER_EN[3] is false, it would be illegal to set - HCOUNTENABLE_EN[3] to true. - - HCOUNTENABLE_EN[0:2] must all be false if `Zicntr` is not implemented. - HCOUNTENABLE_EN[3:31] must all be false if `Zihpm` is not implemented. - schema: - type: array - items: - type: boolean - maxItems: 32 - minItems: 32 - IGNORE_INVALID_VSATP_MODE_WRITES_WHEN_V_EQ_ZERO: - description: | - Whether writes from M-mode, U-mode, or S-mode to vsatp with an illegal mode setting are - ignored (as they are with satp), or if they are treated as WARL, leading to undpredictable - behavior. - schema: - type: boolean - GSTAGE_MODE_BARE: - description: | - Whether or not writing mode=Bare is supported in the `hgatp` register. - schema: - type: boolean - SV32_VSMODE_TRANSLATION: - description: | - Whether or not Sv32 translation is supported in first-stage (VS-stage) - translation. - schema: - type: boolean - extra_validation: | - # Sv32 is only valid if VS-mode can get into XLEN=32 mode - assert (VSXLEN == 32 || VSXLEN == 3264) if SV32_VSMODE_TRANSLATION - SV39_VSMODE_TRANSLATION: - description: | - Whether or not Sv39 translation is supported in first-stage (VS-stage) - translation. - schema: - type: boolean - extra_validation: | - # Sv39 is only valid if VS-mode can get into XLEN=64 mode - assert (VSXLEN == 64 || VSXLEN == 3264) if SV39_VSMODE_TRANSLATION - SV48_VSMODE_TRANSLATION: - description: | - Whether or not Sv48 translation is supported in first-stage (VS-stage) - translation. - schema: - type: boolean - extra_validation: | - # Sv48 is only valid if VS-mode can get into XLEN=64 mode - assert (VSXLEN == 64 || VSXLEN == 3264) if SV48_VSMODE_TRANSLATION - SV57_VSMODE_TRANSLATION: - description: | - Whether or not Sv57 translation is supported in first-stage (VS-stage) - translation. - schema: - type: boolean - extra_validation: | - # Sv57 is only valid if VS-mode can get into XLEN=64 mode - assert (VSXLEN == 64 || VSXLEN == 3264) if SV57_VSMODE_TRANSLATION - SV32X4_TRANSLATION: - description: | - Whether or not Sv32x4 translation mode is supported. - schema: - type: boolean - extra_validation: | - # Sv32x4 is only valid if S-mode can get into XLEN=32 mode - assert SXLEN == 32 || SXLEN == 3264 if SV32X4_TRANSLATION - SV39X4_TRANSLATION: - description: | - Whether or not Sv39x4 translation mode is supported. - schema: - type: boolean - extra_validation: | - # Sv39x4 is only valid if S-mode can get into XLEN=64 mode - assert SXLEN == 64 || SXLEN == 3264 if SV39X4_TRANSLATION - SV48X4_TRANSLATION: - description: | - Whether or not Sv48x4 translation mode is supported. - schema: - type: boolean - extra_validation: | - # Sv48x4 is only valid if S-mode can get into XLEN=64 mode - assert SXLEN == 64 || SXLEN == 3264 if SV48X4_TRANSLATION - SV57X4_TRANSLATION: - description: | - Whether or not Sv57x4 translation mode is supported. - schema: - type: boolean - extra_validation: | - # Sv57x4 is only valid if S-mode can get into XLEN=64 mode - assert SXLEN == 64 || SXLEN == 3264 if SV57X4_TRANSLATION - VMID_WIDTH: - description: | - Number of bits supported in `hgatp.VMID` (i.e., the supported width of a virtual machine ID). - schema: - type: integer - minimum: 0 - maximum: 14 - extra_validation: | - # if XLEN = 32, then VMID MAX is actually 7 - assert VMID_WIDTH <= 7 if SXLEN == 32 - REPORT_GPA_IN_TVAL_ON_LOAD_GUEST_PAGE_FAULT: - description: | - Whether or not GPA >> 2 is written into htval/mtval2 when a load guest page fault occurs. - - If false, 0 will be written into htval/mtval2 on a load guest page fault. - schema: - type: boolean - REPORT_GPA_IN_TVAL_ON_STORE_AMO_GUEST_PAGE_FAULT: - description: | - Whether or not GPA >> 2 is written into htval/mtval2 when a store/amo guest page fault occurs. - - If false, 0 will be written into htval/mtval2 on a store/amo guest page fault. - schema: - type: boolean - REPORT_GPA_IN_TVAL_ON_INSTRUCTION_GUEST_PAGE_FAULT: - description: | - Whether or not GPA >> 2 is written into htval/mtval2 when an instruction guest page fault occurs. - - If false, 0 will be written into htval/mtval2 on an instruction guest page fault. - schema: - type: boolean - REPORT_GPA_IN_TVAL_ON_INTERMEDIATE_GUEST_PAGE_FAULT: - description: | - Whether or not GPA >> 2 is written into htval/mtval2 when a guest page fault occurs while - walking a VS-mode page table. - - If false, 0 will be written into htval/mtval2 on an intermediate guest page fault. - schema: - type: boolean - TINST_VALUE_ON_FINAL_LOAD_GUEST_PAGE_FAULT: - description: | - Value to write into htval/mtval2 when there is a guest page fault on a final translation. - - Possible values: - * "always zero": Always write the value zero - * "always pseudoinstruction": Always write the pseudoinstruction - * "always transformed standard instruction": Always write the transformation of the standard instruction encoding - * "custom": A custom value, which will cause an UNPREDICTABLE event. - schema: - type: string - enum: - - "always zero" - - "always pseudoinstruction" - - "always transformed standard instruction" - - "custom" - TINST_VALUE_ON_FINAL_STORE_AMO_GUEST_PAGE_FAULT: - description: | - Value to write into htval/mtval2 when there is a guest page fault on a final translation. - - Possible values: - * "always zero": Always write the value zero - * "always pseudoinstruction": Always write the pseudoinstruction - * "always transformed standard instruction": Always write the transformation of the standard instruction encoding - * "custom": A custom value, which will cause an UNPREDICTABLE event. - schema: - type: string - enum: - - "always zero" - - "always pseudoinstruction" - - "always transformed standard instruction" - - "custom" - TINST_VALUE_ON_FINAL_INSTRUCTION_GUEST_PAGE_FAULT: - description: | - Value to write into htval/mtval2 when there is a guest page fault on a final translation. - - Possible values: - * "always zero": Always write the value zero - * "always pseudoinstruction": Always write the pseudoinstruction - schema: - type: string - enum: - - "always zero" - - "always pseudoinstruction" - TINST_VALUE_ON_INSTRUCTION_ADDRESS_MISALIGNED: - description: | - Value written into htinst/mtinst when there is an instruction address misaligned exception. - - Possible values: - * "always zero": Always write the value zero - * "custom": Write a custom value, which resuls in UNPREDICTABLE - schema: - type: string - enum: - - "always zero" - - "custom" - TINST_VALUE_ON_BREAKPOINT: - description: | - Value written into htinst/mtinst on a Breakpoint exception from VU/VS-mode. - - Possible values: - * "always zero": Always write the value zero - * "custom": Write a custom value, which resuls in UNPREDICTABLE - schema: - type: string - enum: ['always zero', 'custom'] - TINST_VALUE_ON_VIRTUAL_INSTRUCTION: - description: | - Value written into htinst/mtinst on a VirtualInstruction exception from VU/VS-mode. - - Possible values: - * "always zero": Always write the value zero - * "custom": Write a custom value, which resuls in UNPREDICTABLE - schema: - type: string - enum: ['always zero', 'custom'] - TINST_VALUE_ON_LOAD_ADDRESS_MISALIGNED: - description: | - Value written into htinst/mtinst on a VirtualInstruction exception from VU/VS-mode. - - Possible values: - * "always zero": Always write the value zero - * "always transformed standard instruction": Always write a transformed standard instruction as defined by H - * "custom": Write a custom value, which resuls in UNPREDICTABLE - schema: - type: string - enum: ['always zero', 'always transformed standard instruction', 'custom'] - TINST_VALUE_ON_LOAD_ACCESS_FAULT: - description: | - Value written into htinst/mtinst on an AccessFault exception from VU/VS-mode. - - Possible values: - * "always zero": Always write the value zero - * "always transformed standard instruction": Always write a transformed standard instruction as defined by H - * "custom": Write a custom value, which resuls in UNPREDICTABLE - schema: - type: string - enum: ['always zero', 'always transformed standard instruction', 'custom'] - TINST_VALUE_ON_STORE_AMO_ADDRESS_MISALIGNED: - description: | - Value written into htinst/mtinst on a VirtualInstruction exception from VU/VS-mode. - - Possible values: - * "always zero": Always write the value zero - * "always transformed standard instruction": Always write a transformed standard instruction as defined by H - * "custom": Write a custom value, which resuls in UNPREDICTABLE - schema: - type: string - enum: ['always zero', 'always transformed standard instruction', 'custom'] - TINST_VALUE_ON_STORE_AMO_ACCESS_FAULT: - description: | - Value written into htinst/mtinst on an AccessFault exception from VU/VS-mode. - - Possible values: - * "always zero": Always write the value zero - * "always transformed standard instruction": Always write a transformed standard instruction as defined by H - * "custom": Write a custom value, which resuls in UNPREDICTABLE - schema: - type: string - enum: ['always zero', 'always transformed standard instruction', 'custom'] - TINST_VALUE_ON_UCALL: - description: | - Value written into htinst/mtinst on a UCall exception from VU/VS-mode. - - Possible values: - * "always zero": Always write the value zero - * "custom": Write a custom value, which resuls in UNPREDICTABLE - schema: - type: string - enum: ['always zero', 'custom'] - TINST_VALUE_ON_SCALL: - description: | - Value written into htinst/mtinst on a SCall exception from VU/VS-mode. - - Possible values: - * "always zero": Always write the value zero - * "custom": Write a custom value, which resuls in UNPREDICTABLE - schema: - type: string - enum: ['always zero', 'custom'] - TINST_VALUE_ON_MCALL: - description: | - Value written into htinst/mtinst on a MCall exception from VU/VS-mode. - - Possible values: - * "always zero": Always write the value zero - * "custom": Write a custom value, which resuls in UNPREDICTABLE - schema: - type: string - enum: ['always zero', 'custom'] - TINST_VALUE_ON_VSCALL: - description: | - Value written into htinst/mtinst on a VSCall exception from VU/VS-mode. - - Possible values: - * "always zero": Always write the value zero - * "custom": Write a custom value, which resuls in UNPREDICTABLE - schema: - type: string - enum: ['always zero', 'custom'] - TINST_VALUE_ON_LOAD_PAGE_FAULT: - description: | - Value written into htinst/mtinst on a LoadPageFault exception from VU/VS-mode. - - Possible values: - * "always zero": Always write the value zero - * "always transformed standard instruction": Always write a transformed standard instruction as defined by H - * "custom": Write a custom value, which resuls in UNPREDICTABLE - schema: - type: string - enum: ['always zero', 'always transformed standard instruction', 'custom'] - TINST_VALUE_ON_STORE_AMO_PAGE_FAULT: - description: | - Value written into htinst/mtinst on a StoreAmoPageFault exception from VU/VS-mode. - - Possible values: - * "always zero": Always write the value zero - * "always transformed standard instruction": Always write a transformed standard instruction as defined by H - * "custom": Write a custom value, which resuls in UNPREDICTABLE - schema: - type: string - enum: ['always zero', 'always transformed standard instruction', 'custom'] - TRAP_ON_ECALL_FROM_VS: - description: | - Whether or not an ECALL-from-VS-mode causes a synchronous exception. - - The spec states that implementations may handle ECALLs transparently - without raising a trap, in which case the EEI must provide a builtin. - schema: - type: boolean - default: true \ No newline at end of file + maxItems: 32 + minItems: 32 + IGNORE_INVALID_VSATP_MODE_WRITES_WHEN_V_EQ_ZERO: + description: | + Whether writes from M-mode, U-mode, or S-mode to vsatp with an illegal mode setting are + ignored (as they are with satp), or if they are treated as WARL, leading to undpredictable + behavior. + schema: + type: boolean + GSTAGE_MODE_BARE: + description: | + Whether or not writing mode=Bare is supported in the `hgatp` register. + schema: + type: boolean + SV32_VSMODE_TRANSLATION: + description: | + Whether or not Sv32 translation is supported in first-stage (VS-stage) + translation. + schema: + type: boolean + extra_validation: | + # Sv32 is only valid if VS-mode can get into XLEN=32 mode + assert (VSXLEN == 32 || VSXLEN == 3264) if SV32_VSMODE_TRANSLATION + SV39_VSMODE_TRANSLATION: + description: | + Whether or not Sv39 translation is supported in first-stage (VS-stage) + translation. + schema: + type: boolean + extra_validation: | + # Sv39 is only valid if VS-mode can get into XLEN=64 mode + assert (VSXLEN == 64 || VSXLEN == 3264) if SV39_VSMODE_TRANSLATION + SV48_VSMODE_TRANSLATION: + description: | + Whether or not Sv48 translation is supported in first-stage (VS-stage) + translation. + schema: + type: boolean + extra_validation: | + # Sv48 is only valid if VS-mode can get into XLEN=64 mode + assert (VSXLEN == 64 || VSXLEN == 3264) if SV48_VSMODE_TRANSLATION + SV57_VSMODE_TRANSLATION: + description: | + Whether or not Sv57 translation is supported in first-stage (VS-stage) + translation. + schema: + type: boolean + extra_validation: | + # Sv57 is only valid if VS-mode can get into XLEN=64 mode + assert (VSXLEN == 64 || VSXLEN == 3264) if SV57_VSMODE_TRANSLATION + SV32X4_TRANSLATION: + description: | + Whether or not Sv32x4 translation mode is supported. + schema: + type: boolean + extra_validation: | + # Sv32x4 is only valid if S-mode can get into XLEN=32 mode + assert SXLEN == 32 || SXLEN == 3264 if SV32X4_TRANSLATION + SV39X4_TRANSLATION: + description: | + Whether or not Sv39x4 translation mode is supported. + schema: + type: boolean + extra_validation: | + # Sv39x4 is only valid if S-mode can get into XLEN=64 mode + assert SXLEN == 64 || SXLEN == 3264 if SV39X4_TRANSLATION + SV48X4_TRANSLATION: + description: | + Whether or not Sv48x4 translation mode is supported. + schema: + type: boolean + extra_validation: | + # Sv48x4 is only valid if S-mode can get into XLEN=64 mode + assert SXLEN == 64 || SXLEN == 3264 if SV48X4_TRANSLATION + SV57X4_TRANSLATION: + description: | + Whether or not Sv57x4 translation mode is supported. + schema: + type: boolean + extra_validation: | + # Sv57x4 is only valid if S-mode can get into XLEN=64 mode + assert SXLEN == 64 || SXLEN == 3264 if SV57X4_TRANSLATION + VMID_WIDTH: + description: | + Number of bits supported in `hgatp.VMID` (i.e., the supported width of a virtual machine ID). + schema: + type: integer + minimum: 0 + maximum: 14 + extra_validation: | + # if XLEN = 32, then VMID MAX is actually 7 + assert VMID_WIDTH <= 7 if SXLEN == 32 + REPORT_GPA_IN_TVAL_ON_LOAD_GUEST_PAGE_FAULT: + description: | + Whether or not GPA >> 2 is written into htval/mtval2 when a load guest page fault occurs. + + If false, 0 will be written into htval/mtval2 on a load guest page fault. + schema: + type: boolean + REPORT_GPA_IN_TVAL_ON_STORE_AMO_GUEST_PAGE_FAULT: + description: | + Whether or not GPA >> 2 is written into htval/mtval2 when a store/amo guest page fault occurs. + + If false, 0 will be written into htval/mtval2 on a store/amo guest page fault. + schema: + type: boolean + REPORT_GPA_IN_TVAL_ON_INSTRUCTION_GUEST_PAGE_FAULT: + description: | + Whether or not GPA >> 2 is written into htval/mtval2 when an instruction guest page fault occurs. + + If false, 0 will be written into htval/mtval2 on an instruction guest page fault. + schema: + type: boolean + REPORT_GPA_IN_TVAL_ON_INTERMEDIATE_GUEST_PAGE_FAULT: + description: | + Whether or not GPA >> 2 is written into htval/mtval2 when a guest page fault occurs while + walking a VS-mode page table. + + If false, 0 will be written into htval/mtval2 on an intermediate guest page fault. + schema: + type: boolean + TINST_VALUE_ON_FINAL_LOAD_GUEST_PAGE_FAULT: + description: | + Value to write into htval/mtval2 when there is a guest page fault on a final translation. + + Possible values: + * "always zero": Always write the value zero + * "always pseudoinstruction": Always write the pseudoinstruction + * "always transformed standard instruction": Always write the transformation of the standard instruction encoding + * "custom": A custom value, which will cause an UNPREDICTABLE event. + schema: + type: string + enum: + - "always zero" + - "always pseudoinstruction" + - "always transformed standard instruction" + - "custom" + TINST_VALUE_ON_FINAL_STORE_AMO_GUEST_PAGE_FAULT: + description: | + Value to write into htval/mtval2 when there is a guest page fault on a final translation. + + Possible values: + * "always zero": Always write the value zero + * "always pseudoinstruction": Always write the pseudoinstruction + * "always transformed standard instruction": Always write the transformation of the standard instruction encoding + * "custom": A custom value, which will cause an UNPREDICTABLE event. + schema: + type: string + enum: + - "always zero" + - "always pseudoinstruction" + - "always transformed standard instruction" + - "custom" + TINST_VALUE_ON_FINAL_INSTRUCTION_GUEST_PAGE_FAULT: + description: | + Value to write into htval/mtval2 when there is a guest page fault on a final translation. + + Possible values: + * "always zero": Always write the value zero + * "always pseudoinstruction": Always write the pseudoinstruction + schema: + type: string + enum: + - "always zero" + - "always pseudoinstruction" + TINST_VALUE_ON_INSTRUCTION_ADDRESS_MISALIGNED: + description: | + Value written into htinst/mtinst when there is an instruction address misaligned exception. + + Possible values: + * "always zero": Always write the value zero + * "custom": Write a custom value, which resuls in UNPREDICTABLE + schema: + type: string + enum: + - "always zero" + - "custom" + TINST_VALUE_ON_BREAKPOINT: + description: | + Value written into htinst/mtinst on a Breakpoint exception from VU/VS-mode. + + Possible values: + * "always zero": Always write the value zero + * "custom": Write a custom value, which resuls in UNPREDICTABLE + schema: + type: string + enum: ['always zero', 'custom'] + TINST_VALUE_ON_VIRTUAL_INSTRUCTION: + description: | + Value written into htinst/mtinst on a VirtualInstruction exception from VU/VS-mode. + + Possible values: + * "always zero": Always write the value zero + * "custom": Write a custom value, which resuls in UNPREDICTABLE + schema: + type: string + enum: ['always zero', 'custom'] + TINST_VALUE_ON_LOAD_ADDRESS_MISALIGNED: + description: | + Value written into htinst/mtinst on a VirtualInstruction exception from VU/VS-mode. + + Possible values: + * "always zero": Always write the value zero + * "always transformed standard instruction": Always write a transformed standard instruction as defined by H + * "custom": Write a custom value, which resuls in UNPREDICTABLE + schema: + type: string + enum: ['always zero', 'always transformed standard instruction', 'custom'] + TINST_VALUE_ON_LOAD_ACCESS_FAULT: + description: | + Value written into htinst/mtinst on an AccessFault exception from VU/VS-mode. + + Possible values: + * "always zero": Always write the value zero + * "always transformed standard instruction": Always write a transformed standard instruction as defined by H + * "custom": Write a custom value, which resuls in UNPREDICTABLE + schema: + type: string + enum: ['always zero', 'always transformed standard instruction', 'custom'] + TINST_VALUE_ON_STORE_AMO_ADDRESS_MISALIGNED: + description: | + Value written into htinst/mtinst on a VirtualInstruction exception from VU/VS-mode. + + Possible values: + * "always zero": Always write the value zero + * "always transformed standard instruction": Always write a transformed standard instruction as defined by H + * "custom": Write a custom value, which resuls in UNPREDICTABLE + schema: + type: string + enum: ['always zero', 'always transformed standard instruction', 'custom'] + TINST_VALUE_ON_STORE_AMO_ACCESS_FAULT: + description: | + Value written into htinst/mtinst on an AccessFault exception from VU/VS-mode. + + Possible values: + * "always zero": Always write the value zero + * "always transformed standard instruction": Always write a transformed standard instruction as defined by H + * "custom": Write a custom value, which resuls in UNPREDICTABLE + schema: + type: string + enum: ['always zero', 'always transformed standard instruction', 'custom'] + TINST_VALUE_ON_UCALL: + description: | + Value written into htinst/mtinst on a UCall exception from VU/VS-mode. + + Possible values: + * "always zero": Always write the value zero + * "custom": Write a custom value, which resuls in UNPREDICTABLE + schema: + type: string + enum: ['always zero', 'custom'] + TINST_VALUE_ON_SCALL: + description: | + Value written into htinst/mtinst on a SCall exception from VU/VS-mode. + + Possible values: + * "always zero": Always write the value zero + * "custom": Write a custom value, which resuls in UNPREDICTABLE + schema: + type: string + enum: ['always zero', 'custom'] + TINST_VALUE_ON_MCALL: + description: | + Value written into htinst/mtinst on a MCall exception from VU/VS-mode. + + Possible values: + * "always zero": Always write the value zero + * "custom": Write a custom value, which resuls in UNPREDICTABLE + schema: + type: string + enum: ['always zero', 'custom'] + TINST_VALUE_ON_VSCALL: + description: | + Value written into htinst/mtinst on a VSCall exception from VU/VS-mode. + + Possible values: + * "always zero": Always write the value zero + * "custom": Write a custom value, which resuls in UNPREDICTABLE + schema: + type: string + enum: ['always zero', 'custom'] + TINST_VALUE_ON_LOAD_PAGE_FAULT: + description: | + Value written into htinst/mtinst on a LoadPageFault exception from VU/VS-mode. + + Possible values: + * "always zero": Always write the value zero + * "always transformed standard instruction": Always write a transformed standard instruction as defined by H + * "custom": Write a custom value, which resuls in UNPREDICTABLE + schema: + type: string + enum: ['always zero', 'always transformed standard instruction', 'custom'] + TINST_VALUE_ON_STORE_AMO_PAGE_FAULT: + description: | + Value written into htinst/mtinst on a StoreAmoPageFault exception from VU/VS-mode. + + Possible values: + * "always zero": Always write the value zero + * "always transformed standard instruction": Always write a transformed standard instruction as defined by H + * "custom": Write a custom value, which resuls in UNPREDICTABLE + schema: + type: string + enum: ['always zero', 'always transformed standard instruction', 'custom'] + TRAP_ON_ECALL_FROM_VS: + description: | + Whether or not an ECALL-from-VS-mode causes a synchronous exception. + + The spec states that implementations may handle ECALLs transparently + without raising a trap, in which case the EEI must provide a builtin. + schema: + type: boolean + default: true \ No newline at end of file diff --git a/arch/ext/I.yaml b/arch/ext/I.yaml index a790201c4..72eae0eac 100644 --- a/arch/ext/I.yaml +++ b/arch/ext/I.yaml @@ -1,13 +1,15 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -I: - type: unprivileged - long_name: Base integer ISA (RV32I or RV64I) - versions: - - version: "2.1.0" - state: ratified - ratification_date: 2019-06 - changes: - - ratified RVWMO memory model and exclusion of FENCE.I, counters, and CSR instructions that were in previous base ISA - description: | - Base integer instructions -- TODO \ No newline at end of file +$schema: "ext_schema.json#" +kind: extension +name: I +type: unprivileged +long_name: Base integer ISA (RV32I or RV64I) +versions: +- version: "2.1.0" + state: ratified + ratification_date: 2019-06 + changes: + - ratified RVWMO memory model and exclusion of FENCE.I, counters, and CSR instructions that were in previous base ISA +description: | + Base integer instructions -- TODO \ No newline at end of file diff --git a/arch/ext/M.yaml b/arch/ext/M.yaml index 3578c6d53..e5bf5fa1b 100644 --- a/arch/ext/M.yaml +++ b/arch/ext/M.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -M: - type: unprivileged - long_name: Integer multiply and divide instructions - versions: - - version: "2.0.0" - state: ratified - ratification_date: 2019-12 - description: | - This chapter describes the standard integer multiplication and division - instruction extension, which is named `M` and contains instructions - that multiply or divide values held in two integer registers. +$schema: "ext_schema.json#" +kind: extension +name: M +type: unprivileged +long_name: Integer multiply and divide instructions +versions: +- version: "2.0.0" + state: ratified + ratification_date: 2019-12 +description: | + This chapter describes the standard integer multiplication and division + instruction extension, which is named `M` and contains instructions + that multiply or divide values held in two integer registers. - [TIP] - ==== - We separate integer multiply and divide out from the base to simplify - low-end implementations, or for applications where integer multiply and - divide operations are either infrequent or better handled in attached - accelerators. - ==== - params: - MUTABLE_MISA_M: - description: | - Indicates whether or not the `M` extension can be disabled with the `misa.M` bit. - schema: - type: boolean \ No newline at end of file + [TIP] + ==== + We separate integer multiply and divide out from the base to simplify + low-end implementations, or for applications where integer multiply and + divide operations are either infrequent or better handled in attached + accelerators. + ==== +params: + MUTABLE_MISA_M: + description: | + Indicates whether or not the `M` extension can be disabled with the `misa.M` bit. + schema: + type: boolean \ No newline at end of file diff --git a/arch/ext/MockExt.yaml b/arch/ext/MockExt.yaml index 5299aaf8d..8ba867c8d 100644 --- a/arch/ext/MockExt.yaml +++ b/arch/ext/MockExt.yaml @@ -1,154 +1,156 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -MockExt: - type: privileged - long_name: Mock Extension (for testing database) - description: This is just for testing - versions: - - version: "0.9.9" - state: development - - version: "1.0.0" - state: ratified - ratification_date: 2024-04 - params: - MOCK_ENUM_2_INTS: - description: foo - schema: +$schema: "ext_schema.json#" +kind: extension +name: MockExt +type: privileged +long_name: Mock Extension (for testing database) +description: This is just for testing +versions: +- version: "0.9.9" + state: development +- version: "1.0.0" + state: ratified + ratification_date: 2024-04 +params: + MOCK_ENUM_2_INTS: + description: foo + schema: + type: integer + enum: [32, 64] + MOCK_ENUM_2_STRINGS: + description: foo + schema: + type: string + enum: ["low", "high"] + MOCK_BOOL_1: + description: foo + schema: + type: boolean + MOCK_BOOL_2: + description: foo + schema: + type: boolean + MOCK_32_BIT_INT: + description: foo + schema: + type: integer + minimum: 0 + maximum: 0xffffffff + MOCK_64_BIT_INT: + description: foo + schema: + type: integer + minimum: 0 + maximum: 0xffffffffffffffff + MOCK_1_BIT_INT: + description: foo + schema: + type: integer + minimum: 0 + maximum: 1 + MOCK_2_BIT_INT: + description: foo + schema: + type: integer + minimum: 0 + maximum: 3 + MOCK_25_BIT_INT: + description: foo + schema: + type: integer + minimum: 0 + maximum: 33554431 + MOCK_INT_RANGE_0_TO_2: + description: foo + schema: + type: integer + minimum: 0 + maximum: 2 + MOCK_INT_RANGE_0_TO_127: + description: foo + schema: + type: integer + minimum: 0 + maximum: 127 + MOCK_INT_RANGE_0_TO_999: + description: foo + schema: + type: integer + minimum: 0 + maximum: 999 + MOCK_INT_RANGE_0_TO_1023: + description: foo + schema: + type: integer + minimum: 0 + maximum: 1023 + MOCK_INT_RANGE_1000_TO_2048: + description: foo + schema: + type: integer + minimum: 1000 + maximum: 2048 + MOCK_INT_RANGE_0_TO_128: + description: foo + schema: + type: integer + minimum: 0 + maximum: 128 + MOCK_INT_RANGE_1_TO_128: + description: foo + schema: + type: integer + minimum: 1 + maximum: 128 + MOCK_ARRAY_INT_ENUM: + description: foo + schema: + type: array + items: type: integer - enum: [32, 64] - MOCK_ENUM_2_STRINGS: - description: foo - schema: - type: string - enum: ["low", "high"] - MOCK_BOOL_1: - description: foo - schema: - type: boolean - MOCK_BOOL_2: - description: foo - schema: - type: boolean - MOCK_32_BIT_INT: - description: foo - schema: - type: integer - minimum: 0 - maximum: 0xffffffff - MOCK_64_BIT_INT: - description: foo - schema: - type: integer - minimum: 0 - maximum: 0xffffffffffffffff - MOCK_1_BIT_INT: - description: foo - schema: - type: integer - minimum: 0 - maximum: 1 - MOCK_2_BIT_INT: - description: foo - schema: - type: integer - minimum: 0 - maximum: 3 - MOCK_25_BIT_INT: - description: foo - schema: - type: integer - minimum: 0 - maximum: 33554431 - MOCK_INT_RANGE_0_TO_2: - description: foo - schema: + enum: [0, 1] + minItems: 1 + maxItems: 2 + uniqueItems: true + MOCK_ARRAY_MIN_ONLY: + description: foo + schema: + type: array + items: type: integer - minimum: 0 - maximum: 2 - MOCK_INT_RANGE_0_TO_127: - description: foo - schema: + enum: [0, 1] + minItems: 3 + MOCK_ARRAY_MAX_ONLY: + description: foo + schema: + type: array + items: type: integer - minimum: 0 - maximum: 127 - MOCK_INT_RANGE_0_TO_999: - description: foo - schema: - type: integer - minimum: 0 - maximum: 999 - MOCK_INT_RANGE_0_TO_1023: - description: foo - schema: - type: integer - minimum: 0 - maximum: 1023 - MOCK_INT_RANGE_1000_TO_2048: - description: foo - schema: - type: integer - minimum: 1000 - maximum: 2048 - MOCK_INT_RANGE_0_TO_128: - description: foo - schema: - type: integer - minimum: 0 - maximum: 128 - MOCK_INT_RANGE_1_TO_128: - description: foo - schema: - type: integer - minimum: 1 - maximum: 128 - MOCK_ARRAY_INT_ENUM: - description: foo - schema: - type: array - items: - type: integer - enum: [0, 1] - minItems: 1 - maxItems: 2 - uniqueItems: true - MOCK_ARRAY_MIN_ONLY: - description: foo - schema: - type: array - items: - type: integer - enum: [0, 1] - minItems: 3 - MOCK_ARRAY_MAX_ONLY: - description: foo - schema: - type: array - items: - type: integer - enum: [0, 1] - maxItems: 10 - MOCK_ARRAY_STRING_ENUM1: - description: foo - schema: - type: array - items: - type: string - enum: [ABC, DEF, GHI] - MOCK_ARRAY_STRING_ENUM2: - description: foo - schema: - type: array - items: - type: string - enum: [ABC, DEF, GHI] - MOCK_ARRAY_BOOL_ARRAY_OF_8_FIRST_2_FALSE: - description: foo - schema: - type: array - items: - - const: false - - const: false - additionalItems: - type: boolean - maxItems: 8 - minItems: 8 \ No newline at end of file + enum: [0, 1] + maxItems: 10 + MOCK_ARRAY_STRING_ENUM1: + description: foo + schema: + type: array + items: + type: string + enum: [ABC, DEF, GHI] + MOCK_ARRAY_STRING_ENUM2: + description: foo + schema: + type: array + items: + type: string + enum: [ABC, DEF, GHI] + MOCK_ARRAY_BOOL_ARRAY_OF_8_FIRST_2_FALSE: + description: foo + schema: + type: array + items: + - const: false + - const: false + additionalItems: + type: boolean + maxItems: 8 + minItems: 8 \ No newline at end of file diff --git a/arch/ext/S.yaml b/arch/ext/S.yaml index 3f166fc8f..34e33bc92 100644 --- a/arch/ext/S.yaml +++ b/arch/ext/S.yaml @@ -1,301 +1,303 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -S: - type: privileged - long_name: Supervisor mode - versions: - - version: "1.12.0" - state: ratified - ratification_date: 2021-12 - requires: - name: U - version: "= 1.12.0" - description: | - This chapter describes the RISC-V supervisor-level architecture, which - contains a common core that is used with various supervisor-level - address translation and protection schemes. +$schema: "ext_schema.json#" +kind: extension +name: S +type: privileged +long_name: Supervisor mode +versions: +- version: "1.12.0" + state: ratified + ratification_date: 2021-12 + requires: + name: U + version: "= 1.12.0" +description: | + This chapter describes the RISC-V supervisor-level architecture, which + contains a common core that is used with various supervisor-level + address translation and protection schemes. - [NOTE] - ==== - Supervisor mode is deliberately restricted in terms of interactions with - underlying physical hardware, such as physical memory and device - interrupts, to support clean virtualization. In this spirit, certain - supervisor-level facilities, including requests for timer and - interprocessor interrupts, are provided by implementation-specific - mechanisms. In some systems, a supervisor execution environment (SEE) - provides these facilities in a manner specified by a supervisor binary - interface (SBI). Other systems supply these facilities directly, through - some other implementation-defined mechanism. - ==== - params: - MUTABLE_MISA_S: - description: | - Indicates whether or not the `S` extension can be disabled with the `misa.S` bit. - schema: - type: boolean - extra_validation: | - # If U mode can be disabled, then S mode must also be disabled since you can't - # be in S mode without U mode - assert MUTABLE_MISA_S if MUTABLE_MISA_U - ASID_WIDTH: - description: | - Number of implemented ASID bits. Maximum is 16 for XLEN==64, and 9 for XLEN==32 - schema: - type: integer - minimum: 0 - maximum: 16 - extra_validation: | - assert ASID_WIDTH <= 9 if XLEN == 32 - S_MODE_ENDIANESS: - description: | - Endianess of data in S-mode. Can be one of: + [NOTE] + ==== + Supervisor mode is deliberately restricted in terms of interactions with + underlying physical hardware, such as physical memory and device + interrupts, to support clean virtualization. In this spirit, certain + supervisor-level facilities, including requests for timer and + interprocessor interrupts, are provided by implementation-specific + mechanisms. In some systems, a supervisor execution environment (SEE) + provides these facilities in a manner specified by a supervisor binary + interface (SBI). Other systems supply these facilities directly, through + some other implementation-defined mechanism. + ==== +params: + MUTABLE_MISA_S: + description: | + Indicates whether or not the `S` extension can be disabled with the `misa.S` bit. + schema: + type: boolean + extra_validation: | + # If U mode can be disabled, then S mode must also be disabled since you can't + # be in S mode without U mode + assert MUTABLE_MISA_S if MUTABLE_MISA_U + ASID_WIDTH: + description: | + Number of implemented ASID bits. Maximum is 16 for XLEN==64, and 9 for XLEN==32 + schema: + type: integer + minimum: 0 + maximum: 16 + extra_validation: | + assert ASID_WIDTH <= 9 if XLEN == 32 + S_MODE_ENDIANESS: + description: | + Endianess of data in S-mode. Can be one of: - * little: M-mode data is always little endian - * big: M-mode data is always big endian - * dynamic: M-mode data can be either little or big endian, - depending on the CSR field `mstatus.SBE` - schema: - type: string - enum: [little, big, dynamic] - SXLEN: - description: | - Set of XLENs supported in S-mode. Can be one of: + * little: M-mode data is always little endian + * big: M-mode data is always big endian + * dynamic: M-mode data can be either little or big endian, + depending on the CSR field `mstatus.SBE` + schema: + type: string + enum: [little, big, dynamic] + SXLEN: + description: | + Set of XLENs supported in S-mode. Can be one of: - * 32: SXLEN is always 32 - * 64: SXLEN is always 64 - * 3264: SXLEN can be changed (via mstatus.SXL) between 32 and 64 - schema: - type: integer - enum: [32, 64, 3264] - extra_validation: | - assert SXLEN == 32 if XLEN == 32 - assert (SXLEN != 32) if UXLEN != 32 - REPORT_VA_IN_STVAL_ON_BREAKPOINT: - description: | - When true, `stval` is written with the virtual PC of the EBREAK instruction (same information as `mepc`). + * 32: SXLEN is always 32 + * 64: SXLEN is always 64 + * 3264: SXLEN can be changed (via mstatus.SXL) between 32 and 64 + schema: + type: integer + enum: [32, 64, 3264] + extra_validation: | + assert SXLEN == 32 if XLEN == 32 + assert (SXLEN != 32) if UXLEN != 32 + REPORT_VA_IN_STVAL_ON_BREAKPOINT: + description: | + When true, `stval` is written with the virtual PC of the EBREAK instruction (same information as `mepc`). - When false, `stval` is written with 0 on an EBREAK instruction. + When false, `stval` is written with 0 on an EBREAK instruction. - Regardless, `stval` is always written with a virtual PC when an external breakpoint is generated - schema: - type: boolean - REPORT_VA_IN_STVAL_ON_LOAD_MISALIGNED: - description: | - When true, `stval` is written with the virtual address of a load instruction when the - address is misaligned and MISALIGNED_LDST is false. + Regardless, `stval` is always written with a virtual PC when an external breakpoint is generated + schema: + type: boolean + REPORT_VA_IN_STVAL_ON_LOAD_MISALIGNED: + description: | + When true, `stval` is written with the virtual address of a load instruction when the + address is misaligned and MISALIGNED_LDST is false. - When false, `stval` is written with 0 when a load address is misaligned and - MISALIGNED_LDST is false. - schema: - type: boolean - REPORT_VA_IN_STVAL_ON_STORE_AMO_MISALIGNED: - description: | - When true, `stval` is written with the virtual address of a store instruction when the - address is misaligned and MISALIGNED_LDST is false. + When false, `stval` is written with 0 when a load address is misaligned and + MISALIGNED_LDST is false. + schema: + type: boolean + REPORT_VA_IN_STVAL_ON_STORE_AMO_MISALIGNED: + description: | + When true, `stval` is written with the virtual address of a store instruction when the + address is misaligned and MISALIGNED_LDST is false. - When false, `stval` is written with 0 when a store address is misaligned and - MISALIGNED_LDST is false. - schema: - type: boolean - REPORT_VA_IN_STVAL_ON_INSTRUCTION_MISALIGNED: - description: | - When true, `stval` is written with the virtual PC when an instruction fetch is misaligned. + When false, `stval` is written with 0 when a store address is misaligned and + MISALIGNED_LDST is false. + schema: + type: boolean + REPORT_VA_IN_STVAL_ON_INSTRUCTION_MISALIGNED: + description: | + When true, `stval` is written with the virtual PC when an instruction fetch is misaligned. - When false, `stval` is written with 0 when an instruction fetch is misaligned. + When false, `stval` is written with 0 when an instruction fetch is misaligned. - Note that when IALIGN=16 (i.e., when the `C` or one of the `Zc*` extensions are implemented), - it is impossible to generate a misaligned fetch, and so this parameter has no effect. - schema: - type: boolean - REPORT_VA_IN_STVAL_ON_LOAD_ACCESS_FAULT: - description: | - When true, `stval` is written with the virtual address of a load when it causes a - `LoadAccessFault`. + Note that when IALIGN=16 (i.e., when the `C` or one of the `Zc*` extensions are implemented), + it is impossible to generate a misaligned fetch, and so this parameter has no effect. + schema: + type: boolean + REPORT_VA_IN_STVAL_ON_LOAD_ACCESS_FAULT: + description: | + When true, `stval` is written with the virtual address of a load when it causes a + `LoadAccessFault`. - WHen false, `stval` is written with 0 when a load causes a `LoadAccessFault`. - schema: - type: boolean - REPORT_VA_IN_STVAL_ON_STORE_AMO_ACCESS_FAULT: - description: | - When true, `stval` is written with the virtual address of a store when it causes a - `StoreAmoAccessFault`. + WHen false, `stval` is written with 0 when a load causes a `LoadAccessFault`. + schema: + type: boolean + REPORT_VA_IN_STVAL_ON_STORE_AMO_ACCESS_FAULT: + description: | + When true, `stval` is written with the virtual address of a store when it causes a + `StoreAmoAccessFault`. - WHen false, `stval` is written with 0 when a store causes a `StoreAmoAccessFault`. - schema: - type: boolean - REPORT_VA_IN_STVAL_ON_INSTRUCTION_ACCESS_FAULT: - description: | - When true, `stval` is written with the virtual PC of an instructino when fetch causes an - `InstructionAccessFault`. + WHen false, `stval` is written with 0 when a store causes a `StoreAmoAccessFault`. + schema: + type: boolean + REPORT_VA_IN_STVAL_ON_INSTRUCTION_ACCESS_FAULT: + description: | + When true, `stval` is written with the virtual PC of an instructino when fetch causes an + `InstructionAccessFault`. - WHen false, `stval` is written with 0 when an instruction fetch causes an - `InstructionAccessFault`. - schema: - type: boolean - REPORT_VA_IN_STVAL_ON_LOAD_PAGE_FAULT: - description: | - When true, `stval` is written with the virtual address of a load when it causes a - `LoadPageFault`. + WHen false, `stval` is written with 0 when an instruction fetch causes an + `InstructionAccessFault`. + schema: + type: boolean + REPORT_VA_IN_STVAL_ON_LOAD_PAGE_FAULT: + description: | + When true, `stval` is written with the virtual address of a load when it causes a + `LoadPageFault`. - WHen false, `stval` is written with 0 when a load causes a `LoadPageFault`. - schema: - type: boolean - REPORT_VA_IN_STVAL_ON_STORE_AMO_PAGE_FAULT: - description: | - When true, `stval` is written with the virtual address of a store when it causes a - `StoreAmoPageFault`. + WHen false, `stval` is written with 0 when a load causes a `LoadPageFault`. + schema: + type: boolean + REPORT_VA_IN_STVAL_ON_STORE_AMO_PAGE_FAULT: + description: | + When true, `stval` is written with the virtual address of a store when it causes a + `StoreAmoPageFault`. - WHen false, `stval` is written with 0 when a store causes a `StoreAmoPageFault`. - schema: - type: boolean - REPORT_VA_IN_STVAL_ON_INSTRUCTION_PAGE_FAULT: - description: | - When true, `stval` is written with the virtual PC of an instructino when fetch causes an - `InstructionPageFault`. + WHen false, `stval` is written with 0 when a store causes a `StoreAmoPageFault`. + schema: + type: boolean + REPORT_VA_IN_STVAL_ON_INSTRUCTION_PAGE_FAULT: + description: | + When true, `stval` is written with the virtual PC of an instructino when fetch causes an + `InstructionPageFault`. - WHen false, `stval` is written with 0 when an instruction fetch causes an - `InstructionPageFault`. - schema: - type: boolean - REPORT_ENCODING_IN_STVAL_ON_ILLEGAL_INSTRUCTION: - description: | - When true, `stval` is written with the encoding of an instruction that causes an - `IllegalInstruction` exception. + WHen false, `stval` is written with 0 when an instruction fetch causes an + `InstructionPageFault`. + schema: + type: boolean + REPORT_ENCODING_IN_STVAL_ON_ILLEGAL_INSTRUCTION: + description: | + When true, `stval` is written with the encoding of an instruction that causes an + `IllegalInstruction` exception. - When false `stval` is written with 0 when an `IllegalInstruction` exception occurs. - schema: - type: boolean - STVAL_WIDTH: - description: | - The number of implemented bits in `stval`. + When false `stval` is written with 0 when an `IllegalInstruction` exception occurs. + schema: + type: boolean + STVAL_WIDTH: + description: | + The number of implemented bits in `stval`. - Must be greater than or equal to _max_(`PHYS_ADDR_WIDTH`, `VA_SIZE`) - schema: - type: integer - maximum: 0xffffffffffffffff - SCOUNTENABLE_EN: - description: | - Indicates which counters can delegated via `scounteren` - - An unimplemented counter cannot be specified, i.e., if - HPM_COUNTER_EN[3] is false, it would be illegal to set - SCOUNTENABLE_EN[3] to true. + Must be greater than or equal to _max_(`PHYS_ADDR_WIDTH`, `VA_SIZE`) + schema: + type: integer + maximum: 0xffffffffffffffff + SCOUNTENABLE_EN: + description: | + Indicates which counters can delegated via `scounteren` - SCOUNTENABLE_EN[0:2] must all be false if `Zicntr` is not implemented. - SCOUNTENABLE_EN[3:31] must all be false if `Zihpm` is not implemented. - schema: - type: array - items: - type: boolean - maxItems: 32 - minItems: 32 - extra_validation: | - SCOUNTENABLE_EN[0..2].all? { |en| !en } unless ext?(:Zicntr) - SCOUNTENABLE_EN[3..].all? { |en| !en } unless ext?(:Zihpm) + An unimplemented counter cannot be specified, i.e., if + HPM_COUNTER_EN[3] is false, it would be illegal to set + SCOUNTENABLE_EN[3] to true. - # SCOUNTEN_EN can only be writable if the hpm counter exists - SCOUNTENABLE_EN.each_with_index { |scounten, idx| next if idx < 3; assert (!scounten || HPM_COUNTER_EN[idx]) } - SV_MODE_BARE: - description: | - Whether or not writing mode=Bare is supported in the `satp` register. - schema: - type: boolean - STVEC_MODE_DIRECT: - description: | - Whether or not `stvec.MODE` supports Direct (0). - schema: - type: boolean - extra_validation: - assert STVEC_MODE_DIRECT || STVEC_MODE_VECTORED - STVEC_MODE_VECTORED: - description: | - Whether or not `stvec.MODE` supports Vectored (1). - schema: + SCOUNTENABLE_EN[0:2] must all be false if `Zicntr` is not implemented. + SCOUNTENABLE_EN[3:31] must all be false if `Zihpm` is not implemented. + schema: + type: array + items: type: boolean - extra_validation: - assert STVEC_MODE_DIRECT || STVEC_MODE_VECTORED - SATP_MODE_BARE: - description: | - Whether or not satp.MODE == Bare is supported. - schema: - type: boolean - TRAP_ON_ECALL_FROM_S: - description: | - Whether or not an ECALL-from-S-mode causes a synchronous exception. + maxItems: 32 + minItems: 32 + extra_validation: | + SCOUNTENABLE_EN[0..2].all? { |en| !en } unless ext?(:Zicntr) + SCOUNTENABLE_EN[3..].all? { |en| !en } unless ext?(:Zihpm) - The spec states that implementations may handle ECALLs transparently - without raising a trap, in which case the EEI must provide a builtin. - schema: - type: boolean - default: true - TRAP_ON_SFENCE_VMA_WHEN_SATP_MODE_IS_READ_ONLY: - description: | - For implementations that make `satp`.MODE read-only zero - (always Bare, _i.e._, no virtual translation is implemented), - attempts to execute an SFENCE.VMA instruction might raise an - illegal-instruction exception. + # SCOUNTEN_EN can only be writable if the hpm counter exists + SCOUNTENABLE_EN.each_with_index { |scounten, idx| next if idx < 3; assert (!scounten || HPM_COUNTER_EN[idx]) } + SV_MODE_BARE: + description: | + Whether or not writing mode=Bare is supported in the `satp` register. + schema: + type: boolean + STVEC_MODE_DIRECT: + description: | + Whether or not `stvec.MODE` supports Direct (0). + schema: + type: boolean + extra_validation: + assert STVEC_MODE_DIRECT || STVEC_MODE_VECTORED + STVEC_MODE_VECTORED: + description: | + Whether or not `stvec.MODE` supports Vectored (1). + schema: + type: boolean + extra_validation: + assert STVEC_MODE_DIRECT || STVEC_MODE_VECTORED + SATP_MODE_BARE: + description: | + Whether or not satp.MODE == Bare is supported. + schema: + type: boolean + TRAP_ON_ECALL_FROM_S: + description: | + Whether or not an ECALL-from-S-mode causes a synchronous exception. - TRAP_ON_SFENCE_VMA_WHEN_SATP_MODE_IS_READ_ONLY indicates whether - or not that exception occurs. + The spec states that implementations may handle ECALLs transparently + without raising a trap, in which case the EEI must provide a builtin. + schema: + type: boolean + default: true + TRAP_ON_SFENCE_VMA_WHEN_SATP_MODE_IS_READ_ONLY: + description: | + For implementations that make `satp`.MODE read-only zero + (always Bare, _i.e._, no virtual translation is implemented), + attempts to execute an SFENCE.VMA instruction might raise an + illegal-instruction exception. - TRAP_ON_SFENCE_VMA_WHEN_SATP_MODE_IS_READ_ONLY has no effect when - some virtual translation mode is supported. - schema: - type: boolean - default: false - extra_validation: - assert TRAP_ON_SFENCE_VMA_WHEN_SATP_MODE_IS_READ_ONLY == false if ext?(:Sv32) || ext?(:Sv39) || ext?(:Sv48) || ext?(:Sv57) - MSTATUS_FS_WRITEABLE: - description: | - When `S` is enabled but `F` is not, mstatus.FS is optionally writeable. + TRAP_ON_SFENCE_VMA_WHEN_SATP_MODE_IS_READ_ONLY indicates whether + or not that exception occurs. - This parameter only has an effect when both S and F mode are disabled. - schema: - type: boolean - extra_validation: - assert MSTATUS_FS_WRITEABLE == true if ext?(:F) - MSTATUS_VS_WRITEABLE: - description: | - When `S` is enabled but `V` is not, mstatus.VS is optionally writeable. + TRAP_ON_SFENCE_VMA_WHEN_SATP_MODE_IS_READ_ONLY has no effect when + some virtual translation mode is supported. + schema: + type: boolean + default: false + extra_validation: + assert TRAP_ON_SFENCE_VMA_WHEN_SATP_MODE_IS_READ_ONLY == false if ext?(:Sv32) || ext?(:Sv39) || ext?(:Sv48) || ext?(:Sv57) + MSTATUS_FS_WRITEABLE: + description: | + When `S` is enabled but `F` is not, mstatus.FS is optionally writeable. - This parameter only has an effect when both S and V mode are disabled. - schema: - type: boolean - extra_validation: - assert MSTATUS_VS_WRITEABLE == true if ext?(:V) - MSTATUS_FS_LEGAL_VALUES: - description: | - The set of values that mstatus.FS will accept from a software write. - schema: - type: array - items: - type: integer - enum: [0,1,2,3] - maxItems: 4 - uniqueItems: true - also_defined_in: F - extra_validation: | - assert MSTATUS_FS_LEGAL_VALUES.include?(0) && MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F) - MSTATUS_VS_LEGAL_VALUES: - description: | - The set of values that mstatus.VS will accept from a software write. - schema: - type: array - items: - type: integer - enum: [0,1,2,3] - maxItems: 4 - uniqueItems: true - also_defined_in: V - extra_validation: | - assert MSTATUS_VS_LEGAL_VALUES.include?(0) && MSTATUS_VS_LEGAL_VALUES.include?(3) if ext?(:V) + This parameter only has an effect when both S and F mode are disabled. + schema: + type: boolean + extra_validation: + assert MSTATUS_FS_WRITEABLE == true if ext?(:F) + MSTATUS_VS_WRITEABLE: + description: | + When `S` is enabled but `V` is not, mstatus.VS is optionally writeable. + + This parameter only has an effect when both S and V mode are disabled. + schema: + type: boolean + extra_validation: + assert MSTATUS_VS_WRITEABLE == true if ext?(:V) + MSTATUS_FS_LEGAL_VALUES: + description: | + The set of values that mstatus.FS will accept from a software write. + schema: + type: array + items: + type: integer + enum: [0,1,2,3] + maxItems: 4 + uniqueItems: true + also_defined_in: F + extra_validation: | + assert MSTATUS_FS_LEGAL_VALUES.include?(0) && MSTATUS_FS_LEGAL_VALUES.include?(3) if ext?(:F) + MSTATUS_VS_LEGAL_VALUES: + description: | + The set of values that mstatus.VS will accept from a software write. + schema: + type: array + items: + type: integer + enum: [0,1,2,3] + maxItems: 4 + uniqueItems: true + also_defined_in: V + extra_validation: | + assert MSTATUS_VS_LEGAL_VALUES.include?(0) && MSTATUS_VS_LEGAL_VALUES.include?(3) if ext?(:V) - # 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") - MSTATUS_TVM_IMPLEMENTED: - description: | - Whether or not mstatus.TVM is implemented. + # 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") + MSTATUS_TVM_IMPLEMENTED: + description: | + Whether or not mstatus.TVM is implemented. - When not implemented mstatus.TVM will be read-only-zero. - schema: - type: boolean + When not implemented mstatus.TVM will be read-only-zero. + schema: + type: boolean diff --git a/arch/ext/Sm.yaml b/arch/ext/Sm.yaml index 173be9c73..47b5a40a6 100644 --- a/arch/ext/Sm.yaml +++ b/arch/ext/Sm.yaml @@ -1,508 +1,510 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Sm: - type: privileged - long_name: Machine mode - versions: - - version: "1.11.0" - state: ratified - ratification_date: 2019-12 - changes: - - Moved Machine spec to *Ratified* status. - - Improvements to the description and commentary. - - Specified which interrupt sources are reserved for standard use. - - Allocated some synchronous exception causes for custom use. - - Specified the priority ordering of synchronous exceptions. - - Added specification that xRET instructions may, but are not required - to, clear LR reservations if A extension present. - - Made the `mstatus`.MPP field *WARL*, rather than *WLRL*. - - Made the unused `__x__ip` fields *WPRI*, rather than *WIRI*. - - Made the unused `misa` fields *WARL*, rather than *WIRI*. - - Rectified an editing error that misdescribed the mechanism by which - `mstatus.__x__IE` is written upon an exception. - - Described scheme for emulating misaligned AMOs. - - Specified the behavior of the `misa` and `__x__epc` registers in systems - with variable IALIGN. - - Specified the behavior of writing self-contradictory values to the - `misa` register. - - Specified contents of CSRs across XLEN modification. - - Moved PLIC chapter into its own document. - - version: "1.12.0" - state: ratified - ratification_date: 2021-12 - changes: - - Changed MRET to clear `mstatus`.MPRV when leaving M-mode. - - Relaxed I/O regions have been specified to follow RVWMO. The previous - specification implied that PPO rules other than fences and - acquire/release annotations did not apply. - - Constrained the LR/SC reservation set size and shape when using - page-based virtual memory. - - PMP changes require an SFENCE.VMA on any hart that implements - page-based virtual memory, even if VM is not currently enabled. - - Removed the N extension. - - Defined the mandatory RV32-only CSR `mstatush`, which contains most of - the same fields as the upper 32 bits of RV64's `mstatus`. - - Defined the mandatory CSR `mconfigptr`, which if nonzero contains the - address of a configuration data structure. - - Defined optional `mseccfg` and `mseccfgh` CSRs, which control the - machine's security configuration. - - Defined `menvcfg` CSR (and RV32-only `menvcfgh`), which control various characteristics - of the execution environment. - - Designated part of SYSTEM major opcode for custom use. - - Permitted the unconditional delegation of less-privileged interrupts. - - Added optional big-endian and bi-endian support. - - Made priority of load/store/AMO address-misaligned exceptions - implementation-defined relative to load/store/AMO page-fault and - access-fault exceptions. - - Software breakpoint exceptions are permitted to write either 0 or the - `pc` to `__x__tval`. - - Specified relaxed constraints for implicit reads of non-idempotent regions. - - version: "1.13.0" - state: frozen - ratification_date: 2023-12 - changes: - - Redefined `misa`.MXL to be read-only, making MXLEN a constant. - - Defined the `misa`.B field to reflect that the B extension has been - implemented. - - Defined the `misa`.V field to reflect that the V extension has been - implemented. - - Defined the RV32-only `medelegh` CSR. - - Defined the misaligned atomicity granule PMA, superseding the proposed Zam - extension. - - Defined hardware error and software check exception codes. - - Specified synchronization requirements when changing the PBMTE fields - in `menvcfg` and `henvcfg`. - - Exposed count-overflow interrupts to VS-mode via the Shlcofideleg extension. - - Relaxed behavior of some HINTs when MXLEN > XLEN. - - Transliterated the document from LaTeX into AsciiDoc. - - Included all ratified extensions through March 2024. - - Clarified that "platform- or custom-use" interrupts are actually - "platform-use interrupts", where the platform can choose to make some custom. - - Clarified semantics of explicit accesses to CSRs wider than XLEN bits. - - Clarified that MXLEN≥SXLEN. - - Clarified that WFI is not a HINT instruction. - - Clarified that, for a given exception cause, `__x__tval` might sometimes - be set to a nonzero value but sometimes not. - - Clarified exception behavior of unimplemented or inaccessible CSRs. - - Replaced the concept of vacant memory regions with inaccessible memory or I/O regions. - - Clarified that timer and count-overflow interrupts' arrival in - interrupt-pending registers is not immediate. - - Clarified that MXR affects only explicit memory accesses. - description: | - This chapter describes the machine-level operations available in machine-mode (M-mode), which is - the highest privilege mode in a RISC-V hart. M-mode is used for low-level access to a hardware - platform and is the first mode entered at reset. M-mode can also be used to implement features that - are too difficult or expensive to implement in hardware directly. The RISC-V machine-level ISA - contains a common core that is extended depending on which other privilege levels are supported and - other details of the hardware implementation. - This chapter describes the RISC-V machine-level architecture, which - contains a common core that is used with various supervisor-level - address translation and protection schemes. - interrupt_codes: - - num: 1 - name: Supervisor software interrupt - var: SupervisorSoftware - - num: 3 - name: Machine software interrupt - var: MachineSoftware - - num: 5 - name: Supervisor timer interrupt - var: SupervisorTimer - - num: 7 - name: Machine timer interrupt - var: MachineTimer - - num: 9 - name: Supervisor external interrupt - var: SupervisorExternal - - num: 11 - name: Machine external interrupt - var: MachineExternal - exception_codes: - - num: 0 - name: Instruction address misaligned - var: InstructionAddressMisaligned - - num: 1 - name: Instruction access fault - var: InstructionAccessFault - - num: 2 - name: Illegal instruction - var: IllegalInstruction - - num: 3 - name: Breakpoint - var: Breakpoint - - num: 4 - name: Load address misaligned - var: LoadAddressMisaligned - - num: 5 - name: Load access fault - var: LoadAccessFault - - num: 6 - name: Store/AMO address misaligned - var: StoreAmoAddressMisaligned - - num: 7 - name: Store/AMO access fault - var: StoreAmoAccessFault - - num: 8 - name: Environment call from <%- if ext?(:H) -%>V<%- end -%>U-mode - var: Ucall - - num: 9 - name: Environment call from <%- if ext?(:H) -%>H<%- end -%>S-mode - var: Scall - - num: 11 - name: Environment call from M-mode - var: Mcall - - num: 12 - name: Instruction page fault - var: InstructionPageFault - - num: 13 - name: Load page fault - var: LoadPageFault - - num: 15 - name: Store/AMO page fault - var: StoreAmoPageFault - - num: 18 - name: Software Check - var: SoftwareCheck +$schema: "ext_schema.json#" +kind: extension +name: Sm +type: privileged +long_name: Machine mode +versions: +- version: "1.11.0" + state: ratified + ratification_date: 2019-12 + changes: + - Moved Machine spec to *Ratified* status. + - Improvements to the description and commentary. + - Specified which interrupt sources are reserved for standard use. + - Allocated some synchronous exception causes for custom use. + - Specified the priority ordering of synchronous exceptions. + - Added specification that xRET instructions may, but are not required + to, clear LR reservations if A extension present. + - Made the `mstatus`.MPP field *WARL*, rather than *WLRL*. + - Made the unused `__x__ip` fields *WPRI*, rather than *WIRI*. + - Made the unused `misa` fields *WARL*, rather than *WIRI*. + - Rectified an editing error that misdescribed the mechanism by which + `mstatus.__x__IE` is written upon an exception. + - Described scheme for emulating misaligned AMOs. + - Specified the behavior of the `misa` and `__x__epc` registers in systems + with variable IALIGN. + - Specified the behavior of writing self-contradictory values to the + `misa` register. + - Specified contents of CSRs across XLEN modification. + - Moved PLIC chapter into its own document. +- version: "1.12.0" + state: ratified + ratification_date: 2021-12 + changes: + - Changed MRET to clear `mstatus`.MPRV when leaving M-mode. + - Relaxed I/O regions have been specified to follow RVWMO. The previous + specification implied that PPO rules other than fences and + acquire/release annotations did not apply. + - Constrained the LR/SC reservation set size and shape when using + page-based virtual memory. + - PMP changes require an SFENCE.VMA on any hart that implements + page-based virtual memory, even if VM is not currently enabled. + - Removed the N extension. + - Defined the mandatory RV32-only CSR `mstatush`, which contains most of + the same fields as the upper 32 bits of RV64's `mstatus`. + - Defined the mandatory CSR `mconfigptr`, which if nonzero contains the + address of a configuration data structure. + - Defined optional `mseccfg` and `mseccfgh` CSRs, which control the + machine's security configuration. + - Defined `menvcfg` CSR (and RV32-only `menvcfgh`), which control various characteristics + of the execution environment. + - Designated part of SYSTEM major opcode for custom use. + - Permitted the unconditional delegation of less-privileged interrupts. + - Added optional big-endian and bi-endian support. + - Made priority of load/store/AMO address-misaligned exceptions + implementation-defined relative to load/store/AMO page-fault and + access-fault exceptions. + - Software breakpoint exceptions are permitted to write either 0 or the + `pc` to `__x__tval`. + - Specified relaxed constraints for implicit reads of non-idempotent regions. +- version: "1.13.0" + state: frozen + ratification_date: 2023-12 + changes: + - Redefined `misa`.MXL to be read-only, making MXLEN a constant. + - Defined the `misa`.B field to reflect that the B extension has been + implemented. + - Defined the `misa`.V field to reflect that the V extension has been + implemented. + - Defined the RV32-only `medelegh` CSR. + - Defined the misaligned atomicity granule PMA, superseding the proposed Zam + extension. + - Defined hardware error and software check exception codes. + - Specified synchronization requirements when changing the PBMTE fields + in `menvcfg` and `henvcfg`. + - Exposed count-overflow interrupts to VS-mode via the Shlcofideleg extension. + - Relaxed behavior of some HINTs when MXLEN > XLEN. + - Transliterated the document from LaTeX into AsciiDoc. + - Included all ratified extensions through March 2024. + - Clarified that "platform- or custom-use" interrupts are actually + "platform-use interrupts", where the platform can choose to make some custom. + - Clarified semantics of explicit accesses to CSRs wider than XLEN bits. + - Clarified that MXLEN≥SXLEN. + - Clarified that WFI is not a HINT instruction. + - Clarified that, for a given exception cause, `__x__tval` might sometimes + be set to a nonzero value but sometimes not. + - Clarified exception behavior of unimplemented or inaccessible CSRs. + - Replaced the concept of vacant memory regions with inaccessible memory or I/O regions. + - Clarified that timer and count-overflow interrupts' arrival in + interrupt-pending registers is not immediate. + - Clarified that MXR affects only explicit memory accesses. +description: | + This chapter describes the machine-level operations available in machine-mode (M-mode), which is + the highest privilege mode in a RISC-V hart. M-mode is used for low-level access to a hardware + platform and is the first mode entered at reset. M-mode can also be used to implement features that + are too difficult or expensive to implement in hardware directly. The RISC-V machine-level ISA + contains a common core that is extended depending on which other privilege levels are supported and + other details of the hardware implementation. + This chapter describes the RISC-V machine-level architecture, which + contains a common core that is used with various supervisor-level + address translation and protection schemes. +interrupt_codes: +- num: 1 + name: Supervisor software interrupt + var: SupervisorSoftware +- num: 3 + name: Machine software interrupt + var: MachineSoftware +- num: 5 + name: Supervisor timer interrupt + var: SupervisorTimer +- num: 7 + name: Machine timer interrupt + var: MachineTimer +- num: 9 + name: Supervisor external interrupt + var: SupervisorExternal +- num: 11 + name: Machine external interrupt + var: MachineExternal +exception_codes: +- num: 0 + name: Instruction address misaligned + var: InstructionAddressMisaligned +- num: 1 + name: Instruction access fault + var: InstructionAccessFault +- num: 2 + name: Illegal instruction + var: IllegalInstruction +- num: 3 + name: Breakpoint + var: Breakpoint +- num: 4 + name: Load address misaligned + var: LoadAddressMisaligned +- num: 5 + name: Load access fault + var: LoadAccessFault +- num: 6 + name: Store/AMO address misaligned + var: StoreAmoAddressMisaligned +- num: 7 + name: Store/AMO access fault + var: StoreAmoAccessFault +- num: 8 + name: Environment call from <%- if ext?(:H) -%>V<%- end -%>U-mode + var: Ucall +- num: 9 + name: Environment call from <%- if ext?(:H) -%>H<%- end -%>S-mode + var: Scall +- num: 11 + name: Environment call from M-mode + var: Mcall +- num: 12 + name: Instruction page fault + var: InstructionPageFault +- num: 13 + name: Load page fault + var: LoadPageFault +- num: 15 + name: Store/AMO page fault + var: StoreAmoPageFault +- num: 18 + name: Software Check + var: SoftwareCheck + when: + version: ">= 1.13.0" +params: + XLEN: + description: | + XLEN in M-mode (AKA MXLEN, tracked by issue #52) + schema: + type: integer + enum: [32, 64] + PRECISE_SYNCHRONOUS_EXCEPTIONS: + description: | + Whether or not all synchronous exceptions are precise. + + If false, any exception not otherwise mandated to precise (e.g., PMP violation) + will cause execution to enter an unpredictable state. + schema: + type: boolean + default: true + TRAP_ON_ECALL_FROM_M: + description: | + Whether or not an ECALL-from-M-mode causes a synchronous exception. + + The spec states that implementations may handle ECALLs transparently + without raising a trap, in which case the EEI must provide a builtin. + schema: + type: boolean + default: true + TRAP_ON_EBREAK: + description: | + Whether or not an EBREAK causes a synchronous exception. + + The spec states that implementations may handle EBREAKs transparently + without raising a trap, in which case the EEI must provide a builtin. + schema: + type: boolean + default: true + ARCH_ID: + description: | + Vendor-specific architecture ID in `marchid` + schema: + type: integer + minimum: 0 + maximum: 0xffffffffffffffff + IMP_ID: + description: | + Vendor-specific implementation ID in `mimpid` + schema: + type: integer + minimum: 0 + maximum: 0xffffffffffffffff + VENDOR_ID_BANK: + description: | + JEDEC Vendor ID bank, for `mvendorid` + schema: + type: integer + minimum: 0 + maximum: 33554431 + VENDOR_ID_OFFSET: + description: | + Vendor JEDEC code offset, for `mvendorid` + schema: + type: integer + minimum: 0 + maximum: 127 + MISALIGNED_LDST: + description: | + Does the implementation perform non-atomic misaligned loads and stores to main memory + (does *not* affect misaligned support to device memory)? + If not, the implementation always throws a misaligned exception. + schema: + type: boolean + MISALIGNED_LDST_EXCEPTION_PRIORITY: + description: | + The relative priority of a load/store/AMO exception vs. load/store/AMO page-fault + or access-fault exceptions. + + May be one of: + + [separator="!"] + !=== + ! low ! Misaligned load/store/AMO exceptions are always lower priority than load/store/AMO page-fault and access-fault exceptions. + ! high ! Misaligned load/store/AMO exceptions are always higher priority than load/store/AMO page-fault and access-fault exceptions. + !=== + + MISALIGNED_LDST_EXCEPTION_PRIORITY cannot be "high" when MISALIGNED_MAX_ATOMICITY_GRANULE_SIZE + is non-zero, since the atomicity of an access cannot be determined in that case until after + address translation. + schema: + type: string + enum: ["low", "high"] + extra_validation: | + assert (MISALIGNED_LDST_EXCEPTION_PRIORITY == "low") if MISALIGNED_MAX_ATOMICITY_GRANULE_SIZE.positive? + MISALIGNED_MAX_ATOMICITY_GRANULE_SIZE: + description: | + The maximum granule size, in bytes, that the hart can atomically perform a + misaligned load/store/AMO without raising a Misaligned exception. When MISALIGNED_MAX_ATOMICITY_GRANULE_SIZE is 0, the hart + cannot atomically perform a misaligned load/store/AMO. When a power of two, the hart can + atomically load/store/AMO a misaligned access that is fully contained in a + MISALIGNED_MAX_ATOMICITY_GRANULE_SIZE-aligned region. + + [NOTE] + Even if the hart is capable of performing a misaligned load/store/AMO atomically, + a misaligned exception may still occur if the access does not have the appropriate + Misaligned Atomicity Granule PMA set. + schema: + type: integer + # can't be larger than a page, since there is no way to reconcile that with virtual memory + enum: [0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] + MISALIGNED_SPLIT_STRATEGY: + description: | + When misaligned accesses are supported, this determines the *order* in the implementation appears + to process the load/store, which determines how/which exceptions will be reported + + Options: + + * by_byte: The load/store appears to be broken into byte-sized accesses that processed sequentially from smallest address to largest address + * custom: Something else. Will result in a call to unpredictable() in the execution + schema: + type: string + enum: ["by_byte", "custom"] + TRAP_ON_ILLEGAL_WLRL: + description: | + When true, writing an illegal value to a WLRL CSR field raises an `IllegalInstruction` exception. + + When false, writing an illegal value to a WLRL CSR field is `unpredictable`. + schema: + type: boolean + TRAP_ON_UNIMPLEMENTED_INSTRUCTION: + description: | + When true, fetching an unimplemented instruction from the custom encoding space will cause + an `IllegalInstruction` exception. + + When false, fetching an unimplemented instruction is `UNPREDICTABLE`. + schema: + type: boolean + TRAP_ON_RESERVED_INSTRUCTION: + description: | + When true, fetching an unimplemented and/or undefined instruction from the standard/reserved + encoding space will cause an `IllegalInstruction` exception. + + When false, fetching such an instruction is `UNPREDICTABLE`. + schema: + type: boolean + TRAP_ON_UNIMPLEMENTED_CSR: + description: | + When true, accessing an unimplemented CSR (via a `Zicsr` instruction) will cause an `IllegalInstruction` exception. + + When false, accessing an unimplemented CSR (via a `Zicsr` instruction) is `unpredictable`. + schema: + type: boolean + REPORT_VA_IN_MTVAL_ON_BREAKPOINT: + description: | + When true, `mtval` is written with the virtual PC of the EBREAK instruction (same information as `mepc`). + + When false, `mtval` is written with 0 on an EBREAK instruction. + + Regardless, `mtval` is always written with a virtual PC when an external breakpoint is generated + schema: + type: boolean + REPORT_VA_IN_MTVAL_ON_LOAD_MISALIGNED: + description: | + When true, `mtval` is written with the virtual address of a load instruction when the + address is misaligned and MISALIGNED_LDST is false. + + When false, `mtval` is written with 0 when a load address is misaligned and + MISALIGNED_LDST is false. + schema: + type: boolean + REPORT_VA_IN_MTVAL_ON_STORE_AMO_MISALIGNED: + description: | + When true, `mtval` is written with the virtual address of a store instruction when the + address is misaligned and MISALIGNED_LDST is false. + + When false, `mtval` is written with 0 when a store address is misaligned and + MISALIGNED_LDST is false. + schema: + type: boolean + REPORT_VA_IN_MTVAL_ON_INSTRUCTION_MISALIGNED: + description: | + When true, `mtval` is written with the virtual PC when an instruction fetch is misaligned. + + When false, `mtval` is written with 0 when an instruction fetch is misaligned. + + Note that when IALIGN=16 (i.e., when the `C` or one of the `Zc*` extensions are implemented), + it is impossible to generate a misaligned fetch, and so this parameter has no effect. + schema: + type: boolean + REPORT_VA_IN_MTVAL_ON_LOAD_ACCESS_FAULT: + description: | + When true, `mtval` is written with the virtual address of a load when it causes a + `LoadAccessFault`. + + WHen false, `mtval` is written with 0 when a load causes a `LoadAccessFault`. + schema: + type: boolean + REPORT_VA_IN_MTVAL_ON_STORE_AMO_ACCESS_FAULT: + description: | + When true, `mtval` is written with the virtual address of a store when it causes a + `StoreAmoAccessFault`. + + WHen false, `mtval` is written with 0 when a store causes a `StoreAmoAccessFault`. + schema: + type: boolean + REPORT_VA_IN_MTVAL_ON_INSTRUCTION_ACCESS_FAULT: + description: | + When true, `mtval` is written with the virtual PC of an instructino when fetch causes an + `InstructionAccessFault`. + + WHen false, `mtval` is written with 0 when an instruction fetch causes an + `InstructionAccessFault`. + schema: + type: boolean + REPORT_VA_IN_MTVAL_ON_LOAD_PAGE_FAULT: + description: | + When true, `mtval` is written with the virtual address of a load when it causes a + `LoadPageFault`. + + WHen false, `mtval` is written with 0 when a load causes a `LoadPageFault`. + schema: + type: boolean + REPORT_VA_IN_MTVAL_ON_STORE_AMO_PAGE_FAULT: + description: | + When true, `mtval` is written with the virtual address of a store when it causes a + `StoreAmoPageFault`. + + WHen false, `mtval` is written with 0 when a store causes a `StoreAmoPageFault`. + schema: + type: boolean + REPORT_VA_IN_MTVAL_ON_INSTRUCTION_PAGE_FAULT: + description: | + When true, `mtval` is written with the virtual PC of an instructino when fetch causes an + `InstructionPageFault`. + + WHen false, `mtval` is written with 0 when an instruction fetch causes an + `InstructionPageFault`. + schema: + type: boolean + REPORT_ENCODING_IN_MTVAL_ON_ILLEGAL_INSTRUCTION: + description: | + When true, `mtval` is written with the encoding of an instruction that causes an + `IllegalInstruction` exception. + + When false `mtval` is written with 0 when an `IllegalInstruction` exception occurs. + schema: + type: boolean + MTVAL_WIDTH: + description: | + The number of implemented bits in the `mtval` CSR. + This is the CSR that may be written when a trap is taken into M-mode with exception-specific information to + assist software in handling the trap (e.g., address associated with exception). + + Must be greater than or equal to _max_(`PHYS_ADDR_WIDTH`, `VA_SIZE`) + schema: + type: integer + maximum: 64 + CONFIG_PTR_ADDRESS: + description: | + Physical address of the unified discovery configuration data structure. + This address is reported in the `mconfigptr` CSR. + schema: + type: integer when: - version: ">= 1.13.0" - params: - XLEN: - description: | - XLEN in M-mode (AKA MXLEN, tracked by issue #52) - schema: + version: ">= 1.12.0" + PMA_GRANULARITY: + description: | + log2 of the smallest supported PMA region. + + Generally, for systems with an MMU, should not be smaller than 12, + as that would preclude caching PMP results in the TLB along with + virtual memory translations + schema: + type: integer + minimum: 2 + maximum: 66 + PHYS_ADDR_WIDTH: + description: | + Number of bits in the physical address space. + schema: + type: integer + mimimum: 1 + maximum: 64 + M_MODE_ENDIANESS: + description: | + Endianess of data in M-mode. Can be one of: + + [separator="!"] + !=== + h! little ! M-mode data is always little endian + h! big ! M-mode data is always big endian + h! dynamic ! M-mode data can be either little or big endian, + depending on the CSR field `mstatus.MBE` + !=== + schema: + type: string + enum: [little, big, dynamic] + MISA_CSR_IMPLEMENTED: + description: | + Whether or not the `misa` CSR returns zero or a non-zero value. + + Possible values: + + true:: + The `misa` CSR returns a non-zero value. + + false:: + The `misa` CSR is read-only-0. + schema: + type: boolean + MTVEC_MODES: + description: | + Modes supported by `mtvec.MODE`. If only one, it is assumed to be read-only with that value. + schema: + type: array + items: type: integer - enum: [32, 64] - PRECISE_SYNCHRONOUS_EXCEPTIONS: - description: | - Whether or not all synchronous exceptions are precise. - - If false, any exception not otherwise mandated to precise (e.g., PMP violation) - will cause execution to enter an unpredictable state. - schema: - type: boolean - default: true - TRAP_ON_ECALL_FROM_M: - description: | - Whether or not an ECALL-from-M-mode causes a synchronous exception. - - The spec states that implementations may handle ECALLs transparently - without raising a trap, in which case the EEI must provide a builtin. - schema: - type: boolean - default: true - TRAP_ON_EBREAK: - description: | - Whether or not an EBREAK causes a synchronous exception. - - The spec states that implementations may handle EBREAKs transparently - without raising a trap, in which case the EEI must provide a builtin. - schema: - type: boolean - default: true - ARCH_ID: - description: | - Vendor-specific architecture ID in `marchid` - schema: - type: integer - minimum: 0 - maximum: 0xffffffffffffffff - IMP_ID: - description: | - Vendor-specific implementation ID in `mimpid` - schema: - type: integer - minimum: 0 - maximum: 0xffffffffffffffff - VENDOR_ID_BANK: - description: | - JEDEC Vendor ID bank, for `mvendorid` - schema: - type: integer - minimum: 0 - maximum: 33554431 - VENDOR_ID_OFFSET: - description: | - Vendor JEDEC code offset, for `mvendorid` - schema: - type: integer - minimum: 0 - maximum: 127 - MISALIGNED_LDST: - description: | - Does the implementation perform non-atomic misaligned loads and stores to main memory - (does *not* affect misaligned support to device memory)? - If not, the implementation always throws a misaligned exception. - schema: - type: boolean - MISALIGNED_LDST_EXCEPTION_PRIORITY: - description: | - The relative priority of a load/store/AMO exception vs. load/store/AMO page-fault - or access-fault exceptions. - - May be one of: - - [separator="!"] - !=== - ! low ! Misaligned load/store/AMO exceptions are always lower priority than load/store/AMO page-fault and access-fault exceptions. - ! high ! Misaligned load/store/AMO exceptions are always higher priority than load/store/AMO page-fault and access-fault exceptions. - !=== - - MISALIGNED_LDST_EXCEPTION_PRIORITY cannot be "high" when MISALIGNED_MAX_ATOMICITY_GRANULE_SIZE - is non-zero, since the atomicity of an access cannot be determined in that case until after - address translation. - schema: - type: string - enum: ["low", "high"] - extra_validation: | - assert (MISALIGNED_LDST_EXCEPTION_PRIORITY == "low") if MISALIGNED_MAX_ATOMICITY_GRANULE_SIZE.positive? - MISALIGNED_MAX_ATOMICITY_GRANULE_SIZE: - description: | - The maximum granule size, in bytes, that the hart can atomically perform a - misaligned load/store/AMO without raising a Misaligned exception. When MISALIGNED_MAX_ATOMICITY_GRANULE_SIZE is 0, the hart - cannot atomically perform a misaligned load/store/AMO. When a power of two, the hart can - atomically load/store/AMO a misaligned access that is fully contained in a - MISALIGNED_MAX_ATOMICITY_GRANULE_SIZE-aligned region. - - [NOTE] - Even if the hart is capable of performing a misaligned load/store/AMO atomically, - a misaligned exception may still occur if the access does not have the appropriate - Misaligned Atomicity Granule PMA set. - schema: - type: integer - # can't be larger than a page, since there is no way to reconcile that with virtual memory - enum: [0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] - MISALIGNED_SPLIT_STRATEGY: - description: | - When misaligned accesses are supported, this determines the *order* in the implementation appears - to process the load/store, which determines how/which exceptions will be reported - - Options: - - * by_byte: The load/store appears to be broken into byte-sized accesses that processed sequentially from smallest address to largest address - * custom: Something else. Will result in a call to unpredictable() in the execution - schema: - type: string - enum: ["by_byte", "custom"] - TRAP_ON_ILLEGAL_WLRL: - description: | - When true, writing an illegal value to a WLRL CSR field raises an `IllegalInstruction` exception. - - When false, writing an illegal value to a WLRL CSR field is `unpredictable`. - schema: - type: boolean - TRAP_ON_UNIMPLEMENTED_INSTRUCTION: - description: | - When true, fetching an unimplemented instruction from the custom encoding space will cause - an `IllegalInstruction` exception. - - When false, fetching an unimplemented instruction is `UNPREDICTABLE`. - schema: - type: boolean - TRAP_ON_RESERVED_INSTRUCTION: - description: | - When true, fetching an unimplemented and/or undefined instruction from the standard/reserved - encoding space will cause an `IllegalInstruction` exception. - - When false, fetching such an instruction is `UNPREDICTABLE`. - schema: - type: boolean - TRAP_ON_UNIMPLEMENTED_CSR: - description: | - When true, accessing an unimplemented CSR (via a `Zicsr` instruction) will cause an `IllegalInstruction` exception. - - When false, accessing an unimplemented CSR (via a `Zicsr` instruction) is `unpredictable`. - schema: - type: boolean - REPORT_VA_IN_MTVAL_ON_BREAKPOINT: - description: | - When true, `mtval` is written with the virtual PC of the EBREAK instruction (same information as `mepc`). - - When false, `mtval` is written with 0 on an EBREAK instruction. - - Regardless, `mtval` is always written with a virtual PC when an external breakpoint is generated - schema: - type: boolean - REPORT_VA_IN_MTVAL_ON_LOAD_MISALIGNED: - description: | - When true, `mtval` is written with the virtual address of a load instruction when the - address is misaligned and MISALIGNED_LDST is false. - - When false, `mtval` is written with 0 when a load address is misaligned and - MISALIGNED_LDST is false. - schema: - type: boolean - REPORT_VA_IN_MTVAL_ON_STORE_AMO_MISALIGNED: - description: | - When true, `mtval` is written with the virtual address of a store instruction when the - address is misaligned and MISALIGNED_LDST is false. - - When false, `mtval` is written with 0 when a store address is misaligned and - MISALIGNED_LDST is false. - schema: - type: boolean - REPORT_VA_IN_MTVAL_ON_INSTRUCTION_MISALIGNED: - description: | - When true, `mtval` is written with the virtual PC when an instruction fetch is misaligned. - - When false, `mtval` is written with 0 when an instruction fetch is misaligned. - - Note that when IALIGN=16 (i.e., when the `C` or one of the `Zc*` extensions are implemented), - it is impossible to generate a misaligned fetch, and so this parameter has no effect. - schema: - type: boolean - REPORT_VA_IN_MTVAL_ON_LOAD_ACCESS_FAULT: - description: | - When true, `mtval` is written with the virtual address of a load when it causes a - `LoadAccessFault`. - - WHen false, `mtval` is written with 0 when a load causes a `LoadAccessFault`. - schema: - type: boolean - REPORT_VA_IN_MTVAL_ON_STORE_AMO_ACCESS_FAULT: - description: | - When true, `mtval` is written with the virtual address of a store when it causes a - `StoreAmoAccessFault`. - - WHen false, `mtval` is written with 0 when a store causes a `StoreAmoAccessFault`. - schema: - type: boolean - REPORT_VA_IN_MTVAL_ON_INSTRUCTION_ACCESS_FAULT: - description: | - When true, `mtval` is written with the virtual PC of an instructino when fetch causes an - `InstructionAccessFault`. - - WHen false, `mtval` is written with 0 when an instruction fetch causes an - `InstructionAccessFault`. - schema: - type: boolean - REPORT_VA_IN_MTVAL_ON_LOAD_PAGE_FAULT: - description: | - When true, `mtval` is written with the virtual address of a load when it causes a - `LoadPageFault`. - - WHen false, `mtval` is written with 0 when a load causes a `LoadPageFault`. - schema: - type: boolean - REPORT_VA_IN_MTVAL_ON_STORE_AMO_PAGE_FAULT: - description: | - When true, `mtval` is written with the virtual address of a store when it causes a - `StoreAmoPageFault`. - - WHen false, `mtval` is written with 0 when a store causes a `StoreAmoPageFault`. - schema: - type: boolean - REPORT_VA_IN_MTVAL_ON_INSTRUCTION_PAGE_FAULT: - description: | - When true, `mtval` is written with the virtual PC of an instructino when fetch causes an - `InstructionPageFault`. - - WHen false, `mtval` is written with 0 when an instruction fetch causes an - `InstructionPageFault`. - schema: - type: boolean - REPORT_ENCODING_IN_MTVAL_ON_ILLEGAL_INSTRUCTION: - description: | - When true, `mtval` is written with the encoding of an instruction that causes an - `IllegalInstruction` exception. - - When false `mtval` is written with 0 when an `IllegalInstruction` exception occurs. - schema: - type: boolean - MTVAL_WIDTH: - description: | - The number of implemented bits in the `mtval` CSR. - This is the CSR that may be written when a trap is taken into M-mode with exception-specific information to - assist software in handling the trap (e.g., address associated with exception). - - Must be greater than or equal to _max_(`PHYS_ADDR_WIDTH`, `VA_SIZE`) - schema: - type: integer - maximum: 64 - CONFIG_PTR_ADDRESS: - description: | - Physical address of the unified discovery configuration data structure. - This address is reported in the `mconfigptr` CSR. - schema: - type: integer - when: - version: ">= 1.12.0" - PMA_GRANULARITY: - description: | - log2 of the smallest supported PMA region. - - Generally, for systems with an MMU, should not be smaller than 12, - as that would preclude caching PMP results in the TLB along with - virtual memory translations - schema: - type: integer - minimum: 2 - maximum: 66 - PHYS_ADDR_WIDTH: - description: | - Number of bits in the physical address space. - schema: - type: integer - mimimum: 1 - maximum: 64 - M_MODE_ENDIANESS: - description: | - Endianess of data in M-mode. Can be one of: - - [separator="!"] - !=== - h! little ! M-mode data is always little endian - h! big ! M-mode data is always big endian - h! dynamic ! M-mode data can be either little or big endian, - depending on the CSR field `mstatus.MBE` - !=== - schema: - type: string - enum: [little, big, dynamic] - MISA_CSR_IMPLEMENTED: - description: | - Whether or not the `misa` CSR returns zero or a non-zero value. - - Possible values: - - true:: - The `misa` CSR returns a non-zero value. - - false:: - The `misa` CSR is read-only-0. - schema: - type: boolean - MTVEC_MODES: - description: | - Modes supported by `mtvec.MODE`. If only one, it is assumed to be read-only with that value. - schema: - type: array - items: - type: integer - enum: [0, 1] - minItems: 1 - maxItems: 2 - uniqueItems: true - MTVEC_BASE_ALIGNMENT_DIRECT: - description: | - Byte alignment for `mtvec.BASE` when `mtvec.MODE` is Direct. - - Cannot be less than 4-byte alignment. - schema: - type: integer - minimum: 4 - default: 4 - extra_validation: | - # must be a power of two - assert MTVEC_BASE_ALIGNMENT_DIRECT.to_s(2).count('1') == 1 - MTVEC_BASE_ALIGNMENT_VECTORED: - description: | - Byte alignment for `mtvec.BASE` when `mtvec.MODE` is Vectored. - - Cannot be less than 4-byte alignment. - schema: - type: integer - minimum: 4 - default: 4 - extra_validation: | - # must be a power of two - assert MTVEC_BASE_ALIGNMENT_VECTORED.to_s(2).count('1') == 1 + enum: [0, 1] + minItems: 1 + maxItems: 2 + uniqueItems: true + MTVEC_BASE_ALIGNMENT_DIRECT: + description: | + Byte alignment for `mtvec.BASE` when `mtvec.MODE` is Direct. + + Cannot be less than 4-byte alignment. + schema: + type: integer + minimum: 4 + default: 4 + extra_validation: | + # must be a power of two + assert MTVEC_BASE_ALIGNMENT_DIRECT.to_s(2).count('1') == 1 + MTVEC_BASE_ALIGNMENT_VECTORED: + description: | + Byte alignment for `mtvec.BASE` when `mtvec.MODE` is Vectored. + + Cannot be less than 4-byte alignment. + schema: + type: integer + minimum: 4 + default: 4 + extra_validation: | + # must be a power of two + assert MTVEC_BASE_ALIGNMENT_VECTORED.to_s(2).count('1') == 1 diff --git a/arch/ext/Smaia.yaml b/arch/ext/Smaia.yaml index 2e1dfff67..5e696ae40 100644 --- a/arch/ext/Smaia.yaml +++ b/arch/ext/Smaia.yaml @@ -1,11 +1,13 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Smaia: - long_name: Advanced Interrupt Architecture, M-mode extension - description: Advanced Interrupt Architecture, M-mode extension - type: privileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2023-06 - url: https://github.com/riscv/riscv-aia/releases/download/1.0/riscv-interrupts-1.0.pdf +$schema: "ext_schema.json#" +kind: extension +name: Smaia +long_name: Advanced Interrupt Architecture, M-mode extension +description: Advanced Interrupt Architecture, M-mode extension +type: privileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2023-06 + url: https://github.com/riscv/riscv-aia/releases/download/1.0/riscv-interrupts-1.0.pdf diff --git a/arch/ext/Smcdeleg.yaml b/arch/ext/Smcdeleg.yaml index fa1b43f32..cf03c5253 100644 --- a/arch/ext/Smcdeleg.yaml +++ b/arch/ext/Smcdeleg.yaml @@ -1,35 +1,37 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Smcdeleg: - long_name: Performance counter delegation - description: Performance counter delegation - type: privileged - rvi_jira_issue: RVS-1005 - company: - name: RISC-V International - url: https://riscv.org - doc_license: - name: Creative Commons Attribution 4.0 International License (CC-BY 4.0) - url: https://creativecommons.org/licenses/by/4.0/ - versions: - - version: "1.0.0" - state: ratified - ratification_date: null - repositories: - - url: https://github.com/riscvarchive/riscv-smcdeleg-ssccfg - url: https://github.com/riscvarchive/riscv-smcdeleg-ssccfg/releases/download/v1.0.0/riscv-smcdeleg-ssccfg-v1.0.0.pdf - contributors: - - name: Beeman Strong - email: beeman@rivosinc.com - company: Rivos, Inc. - - name: Atish Patra - email: atishp@rivosinc.com - company: Rivos, Inc. - - name: Allen Baum - email: allen.baum@esperantotech.com - company: Rivos, Inc. - - name: Greg Favor - email: gfavor@ventanamicro.com - company: Ventana Microsystems - - name: John Hauser - email: jh.riscv@jhauser.us \ No newline at end of file +$schema: "ext_schema.json#" +kind: extension +name: Smcdeleg +long_name: Performance counter delegation +description: Performance counter delegation +type: privileged +rvi_jira_issue: RVS-1005 +company: + name: RISC-V International + url: https://riscv.org +doc_license: + name: Creative Commons Attribution 4.0 International License (CC-BY 4.0) + url: https://creativecommons.org/licenses/by/4.0/ +versions: +- version: "1.0.0" + state: ratified + ratification_date: null + repositories: + - url: https://github.com/riscvarchive/riscv-smcdeleg-ssccfg + url: https://github.com/riscvarchive/riscv-smcdeleg-ssccfg/releases/download/v1.0.0/riscv-smcdeleg-ssccfg-v1.0.0.pdf + contributors: + - name: Beeman Strong + email: beeman@rivosinc.com + company: Rivos, Inc. + - name: Atish Patra + email: atishp@rivosinc.com + company: Rivos, Inc. + - name: Allen Baum + email: allen.baum@esperantotech.com + company: Rivos, Inc. + - name: Greg Favor + email: gfavor@ventanamicro.com + company: Ventana Microsystems + - name: John Hauser + email: jh.riscv@jhauser.us \ No newline at end of file diff --git a/arch/ext/Smcntrpmf.yaml b/arch/ext/Smcntrpmf.yaml index d4ffe6012..174269df0 100644 --- a/arch/ext/Smcntrpmf.yaml +++ b/arch/ext/Smcntrpmf.yaml @@ -1,11 +1,13 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Smcntrpmf: - long_name: Cycle and Instret Privilege Mode Filtering - description: Cycle and Instret Privilege Mode Filtering - type: privileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2023-08 - url: https://github.com/riscv/riscv-smcntrpmf/releases/download/v1.0_rc4-frozen/riscv-smcntrpmf-v1.0_rc4.pdf +$schema: "ext_schema.json#" +kind: extension +name: Smcntrpmf +long_name: Cycle and Instret Privilege Mode Filtering +description: Cycle and Instret Privilege Mode Filtering +type: privileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2023-08 + url: https://github.com/riscv/riscv-smcntrpmf/releases/download/v1.0_rc4-frozen/riscv-smcntrpmf-v1.0_rc4.pdf diff --git a/arch/ext/Smhpm.yaml b/arch/ext/Smhpm.yaml index 4039a8884..ebb5b1842 100644 --- a/arch/ext/Smhpm.yaml +++ b/arch/ext/Smhpm.yaml @@ -1,89 +1,91 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Smhpm: - long_name: M-mode programmable hardware performance counters - description: M-mode programmable hardware performance counters - type: privileged - versions: - - version: "1.11.0" - state: ratified - ratification_date: 2019-12 - changes: - - Defined the `mcountinhibit` CSR, which stops performance counters from - incrementing to reduce energy consumption. - - version: "1.12.0" - state: ratified - ratification_date: 2021-12 - changes: - - PMP changes require an SFENCE.VMA on any hart that implements - page-based virtual memory, even if VM is not currently enabled. - - PMP reset values are now platform-defined. - - An additional 48 optional PMP registers have been defined. - - version: "1.13.0" - state: frozen - ratification_date: 2023-12 - params: - HPM_COUNTER_EN: - description: | - List of HPM counters that are enabled. - There is one entry for each hpmcounter. +$schema: "ext_schema.json#" +kind: extension +name: Smhpm +long_name: M-mode programmable hardware performance counters +description: M-mode programmable hardware performance counters +type: privileged +versions: +- version: "1.11.0" + state: ratified + ratification_date: 2019-12 + changes: + - Defined the `mcountinhibit` CSR, which stops performance counters from + incrementing to reduce energy consumption. +- version: "1.12.0" + state: ratified + ratification_date: 2021-12 + changes: + - PMP changes require an SFENCE.VMA on any hart that implements + page-based virtual memory, even if VM is not currently enabled. + - PMP reset values are now platform-defined. + - An additional 48 optional PMP registers have been defined. +- version: "1.13.0" + state: frozen + ratification_date: 2023-12 +params: + HPM_COUNTER_EN: + description: | + List of HPM counters that are enabled. + There is one entry for each hpmcounter. - The first three entries *must* be false (as they correspond to CY, IR, TM in, _e.g._ `mhmpcountinhibit`) - Index 3 in HPM_COUNTER_EN corresponds to hpmcounter3. - Index 31 in HPM_COUNTER_EN corresponds to hpmcounter31. - schema: - type: array - items: - - const: false - - const: false - - const: false - additionalItems: - type: boolean - maxItems: 32 - minItems: 32 - HPM_EVENTS: - description: | - List of defined event numbers that can be written into hpmeventN - schema: - type: array - items: - type: integer - minimum: 0 - maximum: 0x03ffffffffffffff # bits 63-58 are used by `Sscofpmf` - COUNTINHIBIT_EN: - description: | - Indicates which hardware performance monitor counters can be disabled from `mcountinhibit`. + The first three entries *must* be false (as they correspond to CY, IR, TM in, _e.g._ `mhmpcountinhibit`) + Index 3 in HPM_COUNTER_EN corresponds to hpmcounter3. + Index 31 in HPM_COUNTER_EN corresponds to hpmcounter31. + schema: + type: array + items: + - const: false + - const: false + - const: false + additionalItems: + type: boolean + maxItems: 32 + minItems: 32 + HPM_EVENTS: + description: | + List of defined event numbers that can be written into hpmeventN + schema: + type: array + items: + type: integer + minimum: 0 + maximum: 0x03ffffffffffffff # bits 63-58 are used by `Sscofpmf` + COUNTINHIBIT_EN: + description: | + Indicates which hardware performance monitor counters can be disabled from `mcountinhibit`. - An unimplemented counter cannot be specified, i.e., if HPM_COUNTER_EN[3] is false, - it would be illegal to set COUNTINHIBIT_EN[3] to true. + An unimplemented counter cannot be specified, i.e., if HPM_COUNTER_EN[3] is false, + it would be illegal to set COUNTINHIBIT_EN[3] to true. - COUNTINHIBIT_EN[1] can never be true, since it corresponds to `mcountinhibit.TM`, - which is always read-only-0. + COUNTINHIBIT_EN[1] can never be true, since it corresponds to `mcountinhibit.TM`, + which is always read-only-0. - COUNTINHIBIT_EN[3:31] must all be false if `Zihpm` is not implemented. - schema: - type: array - items: - - type: boolean - - const: false - - type: boolean - additionalItems: - type: boolean - maxItems: 32 - minItems: 32 - MCOUNTENABLE_EN: - description: | - Indicates which counters can be delegated via `mcounteren`. + COUNTINHIBIT_EN[3:31] must all be false if `Zihpm` is not implemented. + schema: + type: array + items: + - type: boolean + - const: false + - type: boolean + additionalItems: + type: boolean + maxItems: 32 + minItems: 32 + MCOUNTENABLE_EN: + description: | + Indicates which counters can be delegated via `mcounteren`. - An unimplemented counter cannot be specified, i.e., if - HPM_COUNTER_EN[3] is false, it would be illegal to set - MCOUNTENABLE_EN[3] to true. + An unimplemented counter cannot be specified, i.e., if + HPM_COUNTER_EN[3] is false, it would be illegal to set + MCOUNTENABLE_EN[3] to true. - MCOUNTENABLE_EN[0:2] must all be false if `Zicntr` is not implemented. - MCOUNTENABLE_EN[3:31] must all be false if `Zihpm` is not implemented. - schema: - type: array - items: - type: boolean - maxItems: 32 - minItems: 32 \ No newline at end of file + MCOUNTENABLE_EN[0:2] must all be false if `Zicntr` is not implemented. + MCOUNTENABLE_EN[3:31] must all be false if `Zihpm` is not implemented. + schema: + type: array + items: + type: boolean + maxItems: 32 + minItems: 32 \ No newline at end of file diff --git a/arch/ext/Smpmp.yaml b/arch/ext/Smpmp.yaml index 8d92db00f..f50f73c6d 100644 --- a/arch/ext/Smpmp.yaml +++ b/arch/ext/Smpmp.yaml @@ -1,83 +1,85 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Smpmp: - type: privileged - long_name: Physical Memory Protection - versions: - - version: "1.11.0" - state: ratified - ratification_date: 2019-12 - changes: - - Made the unused `pmpaddr` and `pmpcfg` fields *WARL*, rather than *WIRI*. - - Specified semantics for PMP regions coarser than four bytes. - - version: "1.12.0" - state: ratified - ratification_date: 2021-12 - changes: - - PMP changes require an SFENCE.VMA on any hart that implements - page-based virtual memory, even if VM is not currently enabled. - - PMP reset values are now platform-defined. - - An additional 48 optional PMP registers have been defined. - - version: "1.13.0" - state: frozen - ratification_date: 2023-12 - description: | - To support secure processing and contain faults, it is desirable to limit the physical addresses - accessible by software running on a hart. The optional PMP (Physical Memory Protection) unit - provides per-hart machine-mode control registers to allow physical memory access privileges (read, - write, execute) to be specified for each physical memory region. The PMP values are checked in - parallel with the PMA checks. +$schema: "ext_schema.json#" +kind: extension +name: Smpmp +type: privileged +long_name: Physical Memory Protection +versions: +- version: "1.11.0" + state: ratified + ratification_date: 2019-12 + changes: + - Made the unused `pmpaddr` and `pmpcfg` fields *WARL*, rather than *WIRI*. + - Specified semantics for PMP regions coarser than four bytes. +- version: "1.12.0" + state: ratified + ratification_date: 2021-12 + changes: + - PMP changes require an SFENCE.VMA on any hart that implements + page-based virtual memory, even if VM is not currently enabled. + - PMP reset values are now platform-defined. + - An additional 48 optional PMP registers have been defined. +- version: "1.13.0" + state: frozen + ratification_date: 2023-12 +description: | + To support secure processing and contain faults, it is desirable to limit the physical addresses + accessible by software running on a hart. The optional PMP (Physical Memory Protection) unit + provides per-hart machine-mode control registers to allow physical memory access privileges (read, + write, execute) to be specified for each physical memory region. The PMP values are checked in + parallel with the PMA checks. - [NOTE] - -- - This is a placeholder extension name defined by the `riscv-unified-db` and isn't considered an extension in - the Privileged ISA manual. This was chosen as an extension rather than a M-mode parameter since the - PMP has no visible ISA features (such as read-only-0 CSRs) if not present in an implementation. - Making it an extension in the database prevents having the PMP CSRs show up in implementations that don't have a PMP. - -- - params: - NUM_PMP_ENTRIES: - description: | - Number of implemented PMP entries. Can be any value between 0-64, inclusive. - - The architecture mandates that the number of implemented PMP registers - must appear to be 0, 16, or 64. + [NOTE] + -- + This is a placeholder extension name defined by the `riscv-unified-db` and isn't considered an extension in + the Privileged ISA manual. This was chosen as an extension rather than a M-mode parameter since the + PMP has no visible ISA features (such as read-only-0 CSRs) if not present in an implementation. + Making it an extension in the database prevents having the PMP CSRs show up in implementations that don't have a PMP. + -- +params: + NUM_PMP_ENTRIES: + description: | + Number of implemented PMP entries. Can be any value between 0-64, inclusive. - Therefore, pmp registers will behave as follows according to NUN_PMP_ENTRIES: - - [separator="!"] - !=== - ! NUM_PMP_ENTRIES ! pmpaddr<0-15> / pmpcfg<0-3> ! pmpaddr<16-63> / pmpcfg<4-15> - ! 0 ! N ! N - ! 1-16 ! Y ! N - ! 17-64 ! Y ! Y - !=== + The architecture mandates that the number of implemented PMP registers + must appear to be 0, 16, or 64. - ** N = Not implemented; access will cause `IllegalInstruction` - if TRAP_ON_UNIMPLEMENTED_CSR is true - ** Y = Implemented; access will not cause an exception (from M-mode), but register - may be read-only-zero if NUM_PMP_ENTRIES is less than the corresponding register - - [NOTE] - `pmpcfgN` for an odd N never exists when XLEN == 64 + Therefore, pmp registers will behave as follows according to NUN_PMP_ENTRIES: + + [separator="!"] + !=== + ! NUM_PMP_ENTRIES ! pmpaddr<0-15> / pmpcfg<0-3> ! pmpaddr<16-63> / pmpcfg<4-15> + ! 0 ! N ! N + ! 1-16 ! Y ! N + ! 17-64 ! Y ! Y + !=== - When NUM_PMP_ENTRIES is not exactly 0, 16, or 64, some extant pmp registers, - and associated pmpNcfg, will be read-only zero (but will never cause an exception). - schema: - type: integer - minimum: 0 - maximum: 64 - PMP_GRANULARITY: - description: | - log2 of the smallest supported PMP region. - - Generally, for systems with an MMU, should not be smaller than 12, - as that would preclude caching PMP results in the TLB along with - virtual memory translations + ** N = Not implemented; access will cause `IllegalInstruction` + if TRAP_ON_UNIMPLEMENTED_CSR is true + ** Y = Implemented; access will not cause an exception (from M-mode), but register + may be read-only-zero if NUM_PMP_ENTRIES is less than the corresponding register + + [NOTE] + `pmpcfgN` for an odd N never exists when XLEN == 64 - Note that PMP_GRANULARITY is equal to G+2 (not G) as described in - the privileged architecture. - schema: - type: integer - minimum: 2 - maximum: 66 \ No newline at end of file + When NUM_PMP_ENTRIES is not exactly 0, 16, or 64, some extant pmp registers, + and associated pmpNcfg, will be read-only zero (but will never cause an exception). + schema: + type: integer + minimum: 0 + maximum: 64 + PMP_GRANULARITY: + description: | + log2 of the smallest supported PMP region. + + Generally, for systems with an MMU, should not be smaller than 12, + as that would preclude caching PMP results in the TLB along with + virtual memory translations + + Note that PMP_GRANULARITY is equal to G+2 (not G) as described in + the privileged architecture. + schema: + type: integer + minimum: 2 + maximum: 66 \ No newline at end of file diff --git a/arch/ext/Ssaia.yaml b/arch/ext/Ssaia.yaml index 25b8c9bfe..09bdfe48d 100644 --- a/arch/ext/Ssaia.yaml +++ b/arch/ext/Ssaia.yaml @@ -1,14 +1,16 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Ssaia: - long_name: Advanced Interrupt Architecture, S-mode extension - description: Advanced Interrupt Architecture, S-mode extension - type: privileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2023-06 - url: https://github.com/riscv/riscv-aia/releases/download/1.0/riscv-interrupts-1.0.pdf - requires: - name: S - version: ">= 1.12" +$schema: "ext_schema.json#" +kind: extension +name: Ssaia +long_name: Advanced Interrupt Architecture, S-mode extension +description: Advanced Interrupt Architecture, S-mode extension +type: privileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2023-06 + url: https://github.com/riscv/riscv-aia/releases/download/1.0/riscv-interrupts-1.0.pdf + requires: + name: S + version: ">= 1.12" diff --git a/arch/ext/Ssccfg.yaml b/arch/ext/Ssccfg.yaml index 8cbdc018c..b19973dbc 100644 --- a/arch/ext/Ssccfg.yaml +++ b/arch/ext/Ssccfg.yaml @@ -1,11 +1,13 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Ssccfg: - long_name: Supervisor-mode counter configuration - description: Supervisor-mode counter configuration - type: privileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: null - url: https://docs.google.com/document/d/1s-GeH5XpHBLzbQZucA8DPA7vvF7Xvf_nrPbrU2YLBcE/edit#heading=h.yyrgtolcaczx +$schema: "ext_schema.json#" +kind: extension +name: Ssccfg +long_name: Supervisor-mode counter configuration +description: Supervisor-mode counter configuration +type: privileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: null + url: https://docs.google.com/document/d/1s-GeH5XpHBLzbQZucA8DPA7vvF7Xvf_nrPbrU2YLBcE/edit#heading=h.yyrgtolcaczx diff --git a/arch/ext/Ssccptr.yaml b/arch/ext/Ssccptr.yaml index 4ea276fcd..247dc2b07 100644 --- a/arch/ext/Ssccptr.yaml +++ b/arch/ext/Ssccptr.yaml @@ -1,21 +1,23 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Ssccptr: - long_name: Cacheable and coherent main memory page table reads - description: | - Main memory regions with both the cacheability and coherence PMAs must support hardware page-table reads. +$schema: "ext_schema.json#" +kind: extension +name: Ssccptr +long_name: Cacheable and coherent main memory page table reads +description: | + Main memory regions with both the cacheability and coherence PMAs must support hardware page-table reads. - [NOTE] - This extension was ratified with the RVA20 profiles. - type: privileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: null - url: https://github.com/riscv/riscv-profiles/releases/tag/v1.0 - repositories: - - url: https://github.com/riscv/riscv-profiles - branch: main - contributors: - - name: Krste Asanovic - company: SiFive, Inc. + [NOTE] + This extension was ratified with the RVA20 profiles. +type: privileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: null + url: https://github.com/riscv/riscv-profiles/releases/tag/v1.0 + repositories: + - url: https://github.com/riscv/riscv-profiles + branch: main + contributors: + - name: Krste Asanovic + company: SiFive, Inc. diff --git a/arch/ext/Sscofpmf.yaml b/arch/ext/Sscofpmf.yaml index fe67494e6..17fc12c9e 100644 --- a/arch/ext/Sscofpmf.yaml +++ b/arch/ext/Sscofpmf.yaml @@ -1,13 +1,15 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Sscofpmf: - long_name: Counter Overflow and Privilege Mode Filtering - description: Counter Overflow and Privilege Mode Filtering - type: privileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2023-08 - url: https://drive.google.com/file/d/1KcjgbLM5L1ZKY8934aJl8aQwGlMz6Cbo/view?usp=drive_link - requires: - name: Smhpm +$schema: "ext_schema.json#" +kind: extension +name: Sscofpmf +long_name: Counter Overflow and Privilege Mode Filtering +description: Counter Overflow and Privilege Mode Filtering +type: privileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2023-08 + url: https://drive.google.com/file/d/1KcjgbLM5L1ZKY8934aJl8aQwGlMz6Cbo/view?usp=drive_link + requires: + name: Smhpm diff --git a/arch/ext/Sscounterenw.yaml b/arch/ext/Sscounterenw.yaml index 93a86ba70..97f71aa81 100644 --- a/arch/ext/Sscounterenw.yaml +++ b/arch/ext/Sscounterenw.yaml @@ -1,19 +1,21 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Sscounterenw: - long_name: Supervisor counter enable - description: | - For any hpmcounter that is not read-only zero, the corresponding bit in `scounteren` must be writable. +$schema: "ext_schema.json#" +kind: extension +name: Sscounterenw +long_name: Supervisor counter enable +description: | + For any hpmcounter that is not read-only zero, the corresponding bit in `scounteren` must be writable. - [NOTE] - This extension was ratified with the RVA22 profiles. - type: privileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2023-08 - url: https://drive.google.com/file/d/1KcjgbLM5L1ZKY8934aJl8aQwGlMz6Cbo/view?usp=drive_link - param_constraints: - SCOUNTENABLE_EN: - extra_validation: | - HPM_COUNTER_EN.each_with_index { |hpm_exists, idx| assert(!hpm_exists || SCOUNTENABLE_EN[idx]) } + [NOTE] + This extension was ratified with the RVA22 profiles. +type: privileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2023-08 + url: https://drive.google.com/file/d/1KcjgbLM5L1ZKY8934aJl8aQwGlMz6Cbo/view?usp=drive_link + param_constraints: + SCOUNTENABLE_EN: + extra_validation: | + HPM_COUNTER_EN.each_with_index { |hpm_exists, idx| assert(!hpm_exists || SCOUNTENABLE_EN[idx]) } diff --git a/arch/ext/Sstc.yaml b/arch/ext/Sstc.yaml index 4604c75f0..435287d68 100644 --- a/arch/ext/Sstc.yaml +++ b/arch/ext/Sstc.yaml @@ -1,11 +1,13 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Sstc: - long_name: Superivisor mode timer interrupts - description: Superivisor mode timer interrupts - type: privileged - versions: - - version: "0.9.0" - state: ratified - ratification_date: null - url: https://drive.google.com/file/d/1m84Re2yK8m_vbW7TspvevCDR82MOBaSX/view?usp=drive_link +$schema: "ext_schema.json#" +kind: extension +name: Sstc +long_name: Superivisor mode timer interrupts +description: Superivisor mode timer interrupts +type: privileged +versions: +- version: "0.9.0" + state: ratified + ratification_date: null + url: https://drive.google.com/file/d/1m84Re2yK8m_vbW7TspvevCDR82MOBaSX/view?usp=drive_link diff --git a/arch/ext/Sstvala.yaml b/arch/ext/Sstvala.yaml index 6b46e85cf..118b7811d 100644 --- a/arch/ext/Sstvala.yaml +++ b/arch/ext/Sstvala.yaml @@ -1,61 +1,63 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Sstvala: - long_name: "`stval` requirements for RVA profiles" - description: | - `stval` must be written with the faulting virtual address for load, store, - and instruction page-fault, access-fault, and misaligned exceptions, - and for breakpoint exceptions other than those caused by execution of the - `ebreak` or `c.ebreak instructions. - - For virtual-instruction and illegal-instruction exceptions, - `stval` must be written with the faulting instruction. +$schema: "ext_schema.json#" +kind: extension +name: Sstvala +long_name: "`stval` requirements for RVA profiles" +description: | + `stval` must be written with the faulting virtual address for load, store, + and instruction page-fault, access-fault, and misaligned exceptions, + and for breakpoint exceptions other than those caused by execution of the + `ebreak` or `c.ebreak instructions. + + For virtual-instruction and illegal-instruction exceptions, + `stval` must be written with the faulting instruction. - [NOTE] - This extension was ratified with the RVA20 profiles. - type: privileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: null - url: https://github.com/riscv/riscv-profiles/releases/tag/v1.0 - repositories: - - url: https://github.com/riscv/riscv-profiles - branch: main - contributors: - - name: Krste Asanovic - company: SiFive, Inc. - param_constraints: - REPORT_VA_IN_STVAL_ON_BREAKPOINT: - schema: - const: true - REPORT_VA_IN_STVAL_ON_INSTRUCTION_ACCESS_FAULT: - schema: - const: true - REPORT_VA_IN_STVAL_ON_LOAD_ACCESS_FAULT: - schema: - const: true - REPORT_VA_IN_STVAL_ON_STORE_AMO_ACCESS_FAULT: - schema: - const: true - REPORT_VA_IN_STVAL_ON_INSTRUCTION_PAGE_FAULT: - schema: - const: true - REPORT_VA_IN_STVAL_ON_LOAD_PAGE_FAULT: - schema: - const: true - REPORT_VA_IN_STVAL_ON_STORE_AMO_PAGE_FAULT: - schema: - const: true - REPORT_VA_IN_STVAL_ON_INSTRUCTION_MISALIGNED: - schema: - const: true - REPORT_VA_IN_STVAL_ON_LOAD_MISALIGNED: - schema: - const: true - REPORT_VA_IN_STVAL_ON_STORE_AMO_MISALIGNED: - schema: - const: true - REPORT_ENCODING_IN_STVAL_ON_ILLEGAL_INSTRUCTION: - schema: - const: true \ No newline at end of file + [NOTE] + This extension was ratified with the RVA20 profiles. +type: privileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: null + url: https://github.com/riscv/riscv-profiles/releases/tag/v1.0 + repositories: + - url: https://github.com/riscv/riscv-profiles + branch: main + contributors: + - name: Krste Asanovic + company: SiFive, Inc. + param_constraints: + REPORT_VA_IN_STVAL_ON_BREAKPOINT: + schema: + const: true + REPORT_VA_IN_STVAL_ON_INSTRUCTION_ACCESS_FAULT: + schema: + const: true + REPORT_VA_IN_STVAL_ON_LOAD_ACCESS_FAULT: + schema: + const: true + REPORT_VA_IN_STVAL_ON_STORE_AMO_ACCESS_FAULT: + schema: + const: true + REPORT_VA_IN_STVAL_ON_INSTRUCTION_PAGE_FAULT: + schema: + const: true + REPORT_VA_IN_STVAL_ON_LOAD_PAGE_FAULT: + schema: + const: true + REPORT_VA_IN_STVAL_ON_STORE_AMO_PAGE_FAULT: + schema: + const: true + REPORT_VA_IN_STVAL_ON_INSTRUCTION_MISALIGNED: + schema: + const: true + REPORT_VA_IN_STVAL_ON_LOAD_MISALIGNED: + schema: + const: true + REPORT_VA_IN_STVAL_ON_STORE_AMO_MISALIGNED: + schema: + const: true + REPORT_ENCODING_IN_STVAL_ON_ILLEGAL_INSTRUCTION: + schema: + const: true \ No newline at end of file diff --git a/arch/ext/Sstvecd.yaml b/arch/ext/Sstvecd.yaml index a75432e1f..cbe35c0c1 100644 --- a/arch/ext/Sstvecd.yaml +++ b/arch/ext/Sstvecd.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Sstvecd: - long_name: Direct exception vectoring - description: | - `stvec.MODE` must be capable of holding the value 0 (Direct). - When `stvec.MODE`=Direct, `stvec.BASE` must be capable of holding any valid - four-byte-aligned address. - type: privileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: null - url: https://github.com/riscv/riscv-profiles/releases/tag/v1.0 - repositories: - - url: https://github.com/riscv/riscv-profiles - branch: main - contributors: - - name: Krste Asanovic - company: SiFive, Inc. - param_constraints: - STVEC_MODE_DIRECT: - schema: - const: true +$schema: "ext_schema.json#" +kind: extension +name: Sstvecd +long_name: Direct exception vectoring +description: | + `stvec.MODE` must be capable of holding the value 0 (Direct). + When `stvec.MODE`=Direct, `stvec.BASE` must be capable of holding any valid + four-byte-aligned address. +type: privileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: null + url: https://github.com/riscv/riscv-profiles/releases/tag/v1.0 + repositories: + - url: https://github.com/riscv/riscv-profiles + branch: main + contributors: + - name: Krste Asanovic + company: SiFive, Inc. + param_constraints: + STVEC_MODE_DIRECT: + schema: + const: true diff --git a/arch/ext/Sv32.yaml b/arch/ext/Sv32.yaml index b8599866a..03ab2a2b1 100644 --- a/arch/ext/Sv32.yaml +++ b/arch/ext/Sv32.yaml @@ -1,11 +1,13 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Sv32: - long_name: 32-bit virtual address translation (3 level) - description: 32-bit virtual address translation (3 level) - type: privileged - versions: - - version: "1.12.0" - state: ratified - ratification_date: unknown - url: https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf +$schema: "ext_schema.json#" +kind: extension +name: Sv32 +long_name: 32-bit virtual address translation (3 level) +description: 32-bit virtual address translation (3 level) +type: privileged +versions: +- version: "1.12.0" + state: ratified + ratification_date: unknown + url: https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf diff --git a/arch/ext/Sv39.yaml b/arch/ext/Sv39.yaml index 1782c28eb..35a1d74f3 100644 --- a/arch/ext/Sv39.yaml +++ b/arch/ext/Sv39.yaml @@ -1,11 +1,13 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Sv39: - long_name: 39-bit virtual address translation (3 level) - description: 39-bit virtual address translation (3 level) - type: privileged - versions: - - version: "1.12.0" - state: ratified - ratification_date: unknown - url: https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf +$schema: "ext_schema.json#" +kind: extension +name: Sv39 +long_name: 39-bit virtual address translation (3 level) +description: 39-bit virtual address translation (3 level) +type: privileged +versions: +- version: "1.12.0" + state: ratified + ratification_date: unknown + url: https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf diff --git a/arch/ext/Sv48.yaml b/arch/ext/Sv48.yaml index 9889a3135..ac56935db 100644 --- a/arch/ext/Sv48.yaml +++ b/arch/ext/Sv48.yaml @@ -1,14 +1,16 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Sv48: - long_name: 48-bit virtual address translation (4 level) - description: 48-bit virtual address translation (4 level) - type: privileged - versions: - - version: "1.12.0" - state: ratified - ratification_date: unknown - url: https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf - requires: - name: Sv39 - version: ">= 1.12" +$schema: "ext_schema.json#" +kind: extension +name: Sv48 +long_name: 48-bit virtual address translation (4 level) +description: 48-bit virtual address translation (4 level) +type: privileged +versions: +- version: "1.12.0" + state: ratified + ratification_date: unknown + url: https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf + requires: + name: Sv39 + version: ">= 1.12" diff --git a/arch/ext/Sv57.yaml b/arch/ext/Sv57.yaml index 32dc19c24..49b4447d5 100644 --- a/arch/ext/Sv57.yaml +++ b/arch/ext/Sv57.yaml @@ -1,14 +1,16 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Sv57: - long_name: 57-bit virtual address translation (5 level) - description: 57-bit virtual address translation (5 level) - type: privileged - versions: - - version: "1.12.0" - state: ratified - ratification_date: unknown - url: https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf - requires: - name: Sv48 - version: ">= 1.12" +$schema: "ext_schema.json#" +kind: extension +name: Sv57 +long_name: 57-bit virtual address translation (5 level) +description: 57-bit virtual address translation (5 level) +type: privileged +versions: +- version: "1.12.0" + state: ratified + ratification_date: unknown + url: https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf + requires: + name: Sv48 + version: ">= 1.12" diff --git a/arch/ext/Svade.yaml b/arch/ext/Svade.yaml index 75f5b6a83..b776ca6bb 100644 --- a/arch/ext/Svade.yaml +++ b/arch/ext/Svade.yaml @@ -1,40 +1,42 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Svade: - long_name: Exception on PTE A/D Bits - type: unprivileged - description: | - The Svade extension indicates that hardware does *not* update the A/D bits of a page table - during a page walk. Rather, encountering a PTE with the A bit clear or the D bit clear when - an operation is a write will cause a Page Fault. - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2023-11 - url: https://github.com/riscvarchive/riscv-svadu/releases/download/v1.0/riscv-svadu.pdf - repositories: - - url: https://github.com/riscvarchive/riscv-svadu - branch: main - contributors: - - name: Aaron Durbin - company: Rivos, Inc. - - name: Andrew Waterman - company: SiFive - - name: Earl Killian - company: Aril - - name: Greg Favor - company: Ventana - - name: John Ingalls - company: SiFive - - name: Ken Dockser - company: Tenstorrent - - name: Krste Asanovic - company: SiFive - - name: Paul Donahue - - name: Ved Shanbhogue - company: Rivos, Inc. - conflicts: Svadu - doc_license: - name: Creative Commons Attribution 4.0 International License (CC-BY 4.0) - url: https://creativecommons.org/licenses/by/4.0/ - +$schema: "ext_schema.json#" +kind: extension +name: Svade +long_name: Exception on PTE A/D Bits +type: unprivileged +description: | + The Svade extension indicates that hardware does *not* update the A/D bits of a page table + during a page walk. Rather, encountering a PTE with the A bit clear or the D bit clear when + an operation is a write will cause a Page Fault. +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2023-11 + url: https://github.com/riscvarchive/riscv-svadu/releases/download/v1.0/riscv-svadu.pdf + repositories: + - url: https://github.com/riscvarchive/riscv-svadu + branch: main + contributors: + - name: Aaron Durbin + company: Rivos, Inc. + - name: Andrew Waterman + company: SiFive + - name: Earl Killian + company: Aril + - name: Greg Favor + company: Ventana + - name: John Ingalls + company: SiFive + - name: Ken Dockser + company: Tenstorrent + - name: Krste Asanovic + company: SiFive + - name: Paul Donahue + - name: Ved Shanbhogue + company: Rivos, Inc. +conflicts: Svadu +doc_license: + name: Creative Commons Attribution 4.0 International License (CC-BY 4.0) + url: https://creativecommons.org/licenses/by/4.0/ + diff --git a/arch/ext/Svadu.yaml b/arch/ext/Svadu.yaml index 6dbb8cb07..bd505b5be 100644 --- a/arch/ext/Svadu.yaml +++ b/arch/ext/Svadu.yaml @@ -1,123 +1,125 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Svadu: - long_name: Hardware Updating of PTE A/D Bits - type: unprivileged - description: | - The Svadu extension adds support and CSR controls for hardware updating of PTE - A/D bits. The A and D bits are managed by these extensions as follows: +$schema: "ext_schema.json#" +kind: extension +name: Svadu +long_name: Hardware Updating of PTE A/D Bits +type: unprivileged +description: | + The Svadu extension adds support and CSR controls for hardware updating of PTE + A/D bits. The A and D bits are managed by these extensions as follows: - * When a virtual page is accessed and the A bit is clear, the PTE is updated to - set the A bit. When the virtual page is written and the D bit is clear, the - PTE is updated to set the D bit. When G-stage address translation is in use - and is not Bare, the G-stage virtual pages may be accessed or written by - implicit accesses to VS-level memory management data structures, such as page - tables. + * When a virtual page is accessed and the A bit is clear, the PTE is updated to + set the A bit. When the virtual page is written and the D bit is clear, the + PTE is updated to set the D bit. When G-stage address translation is in use + and is not Bare, the G-stage virtual pages may be accessed or written by + implicit accesses to VS-level memory management data structures, such as page + tables. - * When two-stage address translation is in use, an explicit access may cause - both VS-stage and G-stage PTEs to be updated. The following rules apply to all - PTE updates caused by an explicit or an implicit memory accesses. + - + - The PTE update must be atomic with respect to other accesses to the PTE, and - must atomically perform all tablewalk checks for that leaf PTE as part of, and - before, conditionally updating the PTE value. Updates of the A bit may be - performed as a result of speculation, even if the associated memory access - ultimately is not performed architecturally. However, updates to the D bit, - resulting from an explicit store, must be exact (i.e., non-speculative), and - observed in program order by the local hart. When two-stage address - translation is active, updates of the D bit in G-stage PTEs may be performed - as a result of speculative updates of the A bit in VS-stage PTEs. + - + - The PTE update must appear in the global memory order before the memory access - that caused the PTE update and before any subsequent explicit memory access to - that virtual page by the local hart. The ordering on loads and stores provided - by FENCE instructions and the acquire/release bits on atomic instructions also - orders the PTE updates associated with those loads and stores as observed by - remote harts. + - + - The PTE update is not required to be atomic with respect to the memory access - that caused the update and a trap may occur between the PTE update and the - memory access that caused the PTE update. If a trap occurs then the A and/or D - bit may be updated but the memory access that caused the PTE update might not - occur. The hart must not perform the memory access that caused the PTE update - before the PTE update is globally visible. + * When two-stage address translation is in use, an explicit access may cause + both VS-stage and G-stage PTEs to be updated. The following rules apply to all + PTE updates caused by an explicit or an implicit memory accesses. + + + + The PTE update must be atomic with respect to other accesses to the PTE, and + must atomically perform all tablewalk checks for that leaf PTE as part of, and + before, conditionally updating the PTE value. Updates of the A bit may be + performed as a result of speculation, even if the associated memory access + ultimately is not performed architecturally. However, updates to the D bit, + resulting from an explicit store, must be exact (i.e., non-speculative), and + observed in program order by the local hart. When two-stage address + translation is active, updates of the D bit in G-stage PTEs may be performed + as a result of speculative updates of the A bit in VS-stage PTEs. + + + + The PTE update must appear in the global memory order before the memory access + that caused the PTE update and before any subsequent explicit memory access to + that virtual page by the local hart. The ordering on loads and stores provided + by FENCE instructions and the acquire/release bits on atomic instructions also + orders the PTE updates associated with those loads and stores as observed by + remote harts. + + + + The PTE update is not required to be atomic with respect to the memory access + that caused the update and a trap may occur between the PTE update and the + memory access that caused the PTE update. If a trap occurs then the A and/or D + bit may be updated but the memory access that caused the PTE update might not + occur. The hart must not perform the memory access that caused the PTE update + before the PTE update is globally visible. - [NOTE] - ==== - The PTE updates due to memory accesses ordered-after a FENCE are not themselves - ordered by the FENCE. + [NOTE] + ==== + The PTE updates due to memory accesses ordered-after a FENCE are not themselves + ordered by the FENCE. - Simpler implementations that cannot precisely order the PTE update before - subsequent explicit memory accesses to the associated virtual page by the local - hart may simply order the PTE update before all subsequent explicit memory - accesses to any virtual page by the local hart. - ==== + Simpler implementations that cannot precisely order the PTE update before + subsequent explicit memory accesses to the associated virtual page by the local + hart may simply order the PTE update before all subsequent explicit memory + accesses to any virtual page by the local hart. + ==== - Svadu extension requires the page tables to be located in memory with hardware - page-table write access and _RsrvEventual_ PMA. + Svadu extension requires the page tables to be located in memory with hardware + page-table write access and _RsrvEventual_ PMA. - <<< + <<< - The translation of virtual addresses (or guest physical addresses) to physical - (or guest physical) addresses is accomplished with the same algorithm as - specified in the Supervisor-Level ISA extension (section "Virtual Address - Translation Process") and as modified by the hypervisor extension (section - "Two-stage Address Translation"), except that step 7 of the translation process, - instead of causing a page-fault exception due to A and/or D bits being 0 when - required to be 1, continues as follows: + The translation of virtual addresses (or guest physical addresses) to physical + (or guest physical) addresses is accomplished with the same algorithm as + specified in the Supervisor-Level ISA extension (section "Virtual Address + Translation Process") and as modified by the hypervisor extension (section + "Two-stage Address Translation"), except that step 7 of the translation process, + instead of causing a page-fault exception due to A and/or D bits being 0 when + required to be 1, continues as follows: - [start=7] - . If `pte.a = 0`, or if the original memory access is a store and `pte.d = 0`: - .. If a store to `pte` would violate a PMA or PMP check, raise an access-fault - exception corresponding to the original access type. - .. Perform the following steps atomically: - ... Compare `pte` to the value of the PTE at address `a + va.vpn[i] * PTESIZE`. - ... If the values match, set `pte.a` to 1 and, if the original memory access is - a store, also set `pte.d` to 1. - ... If the comparison fails, return to step 2 + [start=7] + . If `pte.a = 0`, or if the original memory access is a store and `pte.d = 0`: + .. If a store to `pte` would violate a PMA or PMP check, raise an access-fault + exception corresponding to the original access type. + .. Perform the following steps atomically: + ... Compare `pte` to the value of the PTE at address `a + va.vpn[i] * PTESIZE`. + ... If the values match, set `pte.a` to 1 and, if the original memory access is + a store, also set `pte.d` to 1. + ... If the comparison fails, return to step 2 - The Svadu extension adds the `ADUE` bit (bit 61) to `menvcfg`. When - `menvcfg.ADUE` is 1, hardware updating of PTE A/D bits is enabled during - single-stage address translation. When the hypervisor extension is implemented, - if `menvcfg.ADUE` is 1, hardware updating of PTE A/D bits is enabled during - G-stage address translation. When `menvcfg.ADUE` is zero, the implementation - behaves as though Svadu were not implemented. If Svadu is not implemented, - `menvcfg.ADUE` is read-only zero. Furthermore, for implementations with the - hypervisor extension, `henvcfg.ADUE` is read-only zero if `menvcfg.ADUE` is zero. + The Svadu extension adds the `ADUE` bit (bit 61) to `menvcfg`. When + `menvcfg.ADUE` is 1, hardware updating of PTE A/D bits is enabled during + single-stage address translation. When the hypervisor extension is implemented, + if `menvcfg.ADUE` is 1, hardware updating of PTE A/D bits is enabled during + G-stage address translation. When `menvcfg.ADUE` is zero, the implementation + behaves as though Svadu were not implemented. If Svadu is not implemented, + `menvcfg.ADUE` is read-only zero. Furthermore, for implementations with the + hypervisor extension, `henvcfg.ADUE` is read-only zero if `menvcfg.ADUE` is zero. - When the hypervisor extension is implemented, the Svadu extension adds the - `ADUE` bit (bit 61) to `henvcfg`. When `henvcfg.ADUE` is 1, hardware updating of - PTE A/D bits is enabled during VS-stage address translation. When `henvcfg.ADUE` - is zero, the implementation behaves as though Svadu were not implemented for - VS-stage address translation. - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2023-11 - url: https://github.com/riscvarchive/riscv-svadu/releases/download/v1.0/riscv-svadu.pdf - repositories: - - url: https://github.com/riscvarchive/riscv-svadu - branch: main - contributors: - - name: Aaron Durbin - company: Rivos, Inc. - - name: Andrew Waterman - company: SiFive - - name: Earl Killian - company: Aril - - name: Greg Favor - company: Ventana - - name: John Ingalls - company: SiFive - - name: Ken Dockser - company: Tenstorrent - - name: Krste Asanovic - company: SiFive - - name: Paul Donahue - - name: Ved Shanbhogue - company: Rivos, Inc. - conflicts: Svade - doc_license: - name: Creative Commons Attribution 4.0 International License (CC-BY 4.0) - url: https://creativecommons.org/licenses/by/4.0/ - + When the hypervisor extension is implemented, the Svadu extension adds the + `ADUE` bit (bit 61) to `henvcfg`. When `henvcfg.ADUE` is 1, hardware updating of + PTE A/D bits is enabled during VS-stage address translation. When `henvcfg.ADUE` + is zero, the implementation behaves as though Svadu were not implemented for + VS-stage address translation. +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2023-11 + url: https://github.com/riscvarchive/riscv-svadu/releases/download/v1.0/riscv-svadu.pdf + repositories: + - url: https://github.com/riscvarchive/riscv-svadu + branch: main + contributors: + - name: Aaron Durbin + company: Rivos, Inc. + - name: Andrew Waterman + company: SiFive + - name: Earl Killian + company: Aril + - name: Greg Favor + company: Ventana + - name: John Ingalls + company: SiFive + - name: Ken Dockser + company: Tenstorrent + - name: Krste Asanovic + company: SiFive + - name: Paul Donahue + - name: Ved Shanbhogue + company: Rivos, Inc. +conflicts: Svade +doc_license: + name: Creative Commons Attribution 4.0 International License (CC-BY 4.0) + url: https://creativecommons.org/licenses/by/4.0/ + diff --git a/arch/ext/Svbare.yaml b/arch/ext/Svbare.yaml index 4e6073a78..afc684ac2 100644 --- a/arch/ext/Svbare.yaml +++ b/arch/ext/Svbare.yaml @@ -1,20 +1,22 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Svbare: - long_name: Bare virtual addressing - description: | - This extension mandates that the `satp` mode Bare must - be supported. +$schema: "ext_schema.json#" +kind: extension +name: Svbare +long_name: Bare virtual addressing +description: | + This extension mandates that the `satp` mode Bare must + be supported. - [NOTE] - This extension was ratified as part of the RVA22 profile. - versions: - - version: "1.0.0" - state: ratified - ratification_date: null - requires: - name: S - param_constraints: - SATP_MODE_BARE: - schema: - const: true + [NOTE] + This extension was ratified as part of the RVA22 profile. +versions: +- version: "1.0.0" + state: ratified + ratification_date: null + requires: + name: S + param_constraints: + SATP_MODE_BARE: + schema: + const: true diff --git a/arch/ext/Svinval.yaml b/arch/ext/Svinval.yaml index dee3de30e..1ebb07e06 100644 --- a/arch/ext/Svinval.yaml +++ b/arch/ext/Svinval.yaml @@ -1,78 +1,80 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Svinval: - long_name: Fine-grained address-translation cache invalidation - description: | - The `Svinval` extension splits `sfence.vma`, `hfence.vma`, and `hfence.gvma` instructions into - finer-grained invalidation and ordering operations that can be more efficiently batched or - pipelined on certain classes of high-performance implementation. +$schema: "ext_schema.json#" +kind: extension +name: Svinval +long_name: Fine-grained address-translation cache invalidation +description: | + The `Svinval` extension splits `sfence.vma`, `hfence.vma`, and `hfence.gvma` instructions into + finer-grained invalidation and ordering operations that can be more efficiently batched or + pipelined on certain classes of high-performance implementation. - The `sinval.vma` instruction invalidates any address-translation cache entries that an - `sfence.vma` instruction with the same values of rs1 and rs2 would invalidate. - However, unlike `sfence.vma`, `sinval.vma` instructions are only ordered with respect to - `sfence.vma`, `sfence.w.inval`, and `sfence.inval.ir` instructions as defined below. + The `sinval.vma` instruction invalidates any address-translation cache entries that an + `sfence.vma` instruction with the same values of rs1 and rs2 would invalidate. + However, unlike `sfence.vma`, `sinval.vma` instructions are only ordered with respect to + `sfence.vma`, `sfence.w.inval`, and `sfence.inval.ir` instructions as defined below. - The `sfence.w.inval` instruction guarantees that any previous stores already visible to the - current RISC-V hart are ordered before subsequent `sinval.vma` instructions executed by the - same hart. The `sfence.inval.ir` instruction guarantees that any previous `sinval.vma` - instructions executed by the current hart are ordered before subsequent implicit references by - that hart to the memory-management data structures. + The `sfence.w.inval` instruction guarantees that any previous stores already visible to the + current RISC-V hart are ordered before subsequent `sinval.vma` instructions executed by the + same hart. The `sfence.inval.ir` instruction guarantees that any previous `sinval.vma` + instructions executed by the current hart are ordered before subsequent implicit references by + that hart to the memory-management data structures. - When executed in order (but not necessarily consecutively) by a single hart, the sequence - `sfence.w.inval`, `sinval.vma`, and `sfence.inval.ir` has the same effect as a hypothetical - `sfence.vma` instruction in which: + When executed in order (but not necessarily consecutively) by a single hart, the sequence + `sfence.w.inval`, `sinval.vma`, and `sfence.inval.ir` has the same effect as a hypothetical + `sfence.vma` instruction in which: - * the values of _rs1_ and _rs2_ for the `sfence.vma` are the same as those used in the `sinval.vma`, - * reads and writes prior to the `sfence.w.inval` are considered to be those prior to the `sfence.vma`, and - * reads and writes following the `sfence.inval.ir` are considered to be those subsequent to the `sfence.vma`. + * the values of _rs1_ and _rs2_ for the `sfence.vma` are the same as those used in the `sinval.vma`, + * reads and writes prior to the `sfence.w.inval` are considered to be those prior to the `sfence.vma`, and + * reads and writes following the `sfence.inval.ir` are considered to be those subsequent to the `sfence.vma`. - If the hypervisor extension is implemented, the `Svinval` extension also provides two additional - instructions: `hinval.vvma` and `hinval.gvma`. - These have the same semantics as `sinval.vma`, except that they combine with `sfence.w.inval` - and `sfence.inval.ir` to replace `hfence.vvma` and `hfence.gvma`, respectively, - instead of `sfence.vma`. - In addition, `hinval.gvma` uses VMIDs instead of ASIDs. + If the hypervisor extension is implemented, the `Svinval` extension also provides two additional + instructions: `hinval.vvma` and `hinval.gvma`. + These have the same semantics as `sinval.vma`, except that they combine with `sfence.w.inval` + and `sfence.inval.ir` to replace `hfence.vvma` and `hfence.gvma`, respectively, + instead of `sfence.vma`. + In addition, `hinval.gvma` uses VMIDs instead of ASIDs. - `sinval.vma`, `hinval.vvma`, and `hinval.gvma` require the same permissions and raise the same - exceptions as `sfence.vma`, `hfence.vvma`, and `hfence.gvma`, respectively. - In particular, an attempt to execute any of these instructions in U-mode always raises an - IllegalInstruction exception, and an attempt to execute `sinval.vma` or `hinval.gvma` in S-mode - or HS-mode when `mstatus.TVM`=1 also raises an IllegalInstruction exception. - An attempt to execute `hinval.vvma` or `hinval.gvma` in VS-mode or VU-mode, or to execute - `sinval.vma` in VU-mode, raises a `VirtualInstruction` exception. - When `hstatus.VTVM`=1, an attempt to execute `sinval.vma` in VS-mode also raises a - `VirtualInstruction` exception. + `sinval.vma`, `hinval.vvma`, and `hinval.gvma` require the same permissions and raise the same + exceptions as `sfence.vma`, `hfence.vvma`, and `hfence.gvma`, respectively. + In particular, an attempt to execute any of these instructions in U-mode always raises an + IllegalInstruction exception, and an attempt to execute `sinval.vma` or `hinval.gvma` in S-mode + or HS-mode when `mstatus.TVM`=1 also raises an IllegalInstruction exception. + An attempt to execute `hinval.vvma` or `hinval.gvma` in VS-mode or VU-mode, or to execute + `sinval.vma` in VU-mode, raises a `VirtualInstruction` exception. + When `hstatus.VTVM`=1, an attempt to execute `sinval.vma` in VS-mode also raises a + `VirtualInstruction` exception. - Attempting to execute `sfence.w.inval` or `sfence.inval.ir` in U-mode raises an `IllegalInstruction` - exception. - Doing so in VU-mode raises a `VirtualInstruction` exception. - `sfence.w.inval` and `sfence.inval.ir` are unaffected by the `mstatus.TVM` and `hstatus.VTVM` - fields and hence are always permitted in S-mode and VS-mode. + Attempting to execute `sfence.w.inval` or `sfence.inval.ir` in U-mode raises an `IllegalInstruction` + exception. + Doing so in VU-mode raises a `VirtualInstruction` exception. + `sfence.w.inval` and `sfence.inval.ir` are unaffected by the `mstatus.TVM` and `hstatus.VTVM` + fields and hence are always permitted in S-mode and VS-mode. - [NOTE] - -- - `sfence.w.inval` and `sfence.inval.ir` instructions do not need to be trapped when `mstatus.TVM`=1 - or when `hstatus.VTVM`=1, as they only have ordering effects but no visible side effects. - Trapping of the `sinval.vma` instruction is sufficient to enable emulation of the intended - overall TLB maintenance functionality. + [NOTE] + -- + `sfence.w.inval` and `sfence.inval.ir` instructions do not need to be trapped when `mstatus.TVM`=1 + or when `hstatus.VTVM`=1, as they only have ordering effects but no visible side effects. + Trapping of the `sinval.vma` instruction is sufficient to enable emulation of the intended + overall TLB maintenance functionality. - In typical usage, software will invalidate a range of virtual addresses in the address-translation - caches by executing an `sfence.w.inval` instruction, executing a series of `sinval.vma`, - `hinval.vvma`, or `hinval.gvma` instructions to the addresses (and optionally ASIDs or VMIDs) - in question, and then executing an `sfence.inval.ir` instruction. + In typical usage, software will invalidate a range of virtual addresses in the address-translation + caches by executing an `sfence.w.inval` instruction, executing a series of `sinval.vma`, + `hinval.vvma`, or `hinval.gvma` instructions to the addresses (and optionally ASIDs or VMIDs) + in question, and then executing an `sfence.inval.ir` instruction. - High-performance implementations will be able to pipeline the address-translation cache - invalidation operations, and will defer any pipeline stalls or other memory ordering enforcement - until an `sfence.w.inval`, `sfence.inval.ir`, `sfence.vma`, `hfence.gvma`, or `hfence.vvma` - instruction is executed. + High-performance implementations will be able to pipeline the address-translation cache + invalidation operations, and will defer any pipeline stalls or other memory ordering enforcement + until an `sfence.w.inval`, `sfence.inval.ir`, `sfence.vma`, `hfence.gvma`, or `hfence.vvma` + instruction is executed. - Simpler implementations may implement `sinval.vma`, `hinval.vvma`, and `hinval.gvma` identically - to `sfence.vma`, `hfence.vvma`, and `hfence.gvma`, respectively, while implementing - `sfence.w.inval` and `sfence.inval.ir` instructions as no-ops. - -- - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2021-11 - requires: - name: S + Simpler implementations may implement `sinval.vma`, `hinval.vvma`, and `hinval.gvma` identically + to `sfence.vma`, `hfence.vvma`, and `hfence.gvma`, respectively, while implementing + `sfence.w.inval` and `sfence.inval.ir` instructions as no-ops. + -- +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2021-11 + requires: + name: S diff --git a/arch/ext/Svnapot.yaml b/arch/ext/Svnapot.yaml index 14cf6cd62..af42265d3 100644 --- a/arch/ext/Svnapot.yaml +++ b/arch/ext/Svnapot.yaml @@ -1,173 +1,175 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Svnapot: - long_name: Naturally-aligned Power of Two Translation Contiguity - description: | - In Sv39, Sv48, and Sv57, when a PTE has N=1, the PTE represents a - translation that is part of a range of contiguous virtual-to-physical - translations with the same values for PTE bits 5-0. Such ranges must be - of a naturally aligned power-of-2 (NAPOT) granularity larger than the - base page size. - - The Svnapot extension depends on Sv39. - - [[ptenapot]] - .Page table entry encodings when __pte__.N=1 - [%autowidth,float="center",align="center",cols="^,^,<,^",options="header"] - |=== - |i |_pte_._ppn_[_i_] |Description |_pte_.__napot_bits__ - |0 + - 0 + - 0 + - 0 + - 0 + - ≥1 - |`x xxxx xxx1` + - `x xxxx xx1x` + - `x xxxx x1xx` + - `x xxxx 1000` + - `x xxxx 0xxx` + - `x xxxx xxxx` - |_Reserved_ + - _Reserved_ + - _Reserved_ + - 64 KiB contiguous region + - _Reserved_ + - _Reserved_ - | - + - - + - - + - 4 + - - + - - - |=== - - NAPOT PTEs behave identically to non-NAPOT PTEs within the - address-translation algorithm in <>, - except that: - - * If the encoding in _pte_ is valid according to - <>, then instead of returning the original - value of _pte_, implicit reads of a NAPOT PTE return a copy - of _pte_ in which __pte__.__ppn__[__i__][__pte__.__napot_bits__-1:0] is replaced by - __vpn__[__i__][__pte__.__napot_bits__-1:0]. If the encoding in _pte_ is reserved according to - <>, then a page-fault exception must be raised. - * Implicit reads of NAPOT page table entries may create - address-translation cache entries mapping - _a_ + _j_*PTESIZE to a copy of _pte_ in which _pte_._ppn_[_i_][_pte_.__napot_bits__-1:0] - is replaced by _vpn[i][pte.napot_bits_-1:0], for any or all _j_ such that - __j__ >> __napot_bits__ = __vpn__[__i__] >> __napot_bits__, all for the address space identified in _satp_ as loaded by step 1. - - [NOTE] - ==== - The motivation for a NAPOT PTE is that it can be cached in a TLB as one - or more entries representing the contiguous region as if it were a - single (large) page covered by a single translation. This compaction can - help relieve TLB pressure in some scenarios. The encoding is designed to - fit within the pre-existing Sv39, Sv48, and Sv57 PTE formats so as not - to disrupt existing implementations or designs that choose not to - implement the scheme. It is also designed so as not to complicate the - definition of the address-translation algorithm. - - The address translation cache abstraction captures the behavior that - would result from the creation of a single TLB entry covering the entire - NAPOT region. It is also designed to be consistent with implementations - that support NAPOT PTEs by splitting the NAPOT region into TLB entries - covering any smaller power-of-two region sizes. For example, a 64 KiB - NAPOT PTE might trigger the creation of 16 standard 4 KiB TLB entries, - all with contents generated from the NAPOT PTE (even if the PTEs for the - other 4 KiB regions have different contents). - - In typical usage scenarios, NAPOT PTEs in the same region will have the - same attributes, same PPNs, and same values for bits 5-0. RSW remains - reserved for supervisor software control. It is the responsibility of - the OS and/or hypervisor to configure the page tables in such a way that - there are no inconsistencies between NAPOT PTEs and other NAPOT or - non-NAPOT PTEs that overlap the same address range. If an update needs - to be made, the OS generally should first mark all of the PTEs invalid, - then issue SFENCE.VMA instruction(s) covering all 4 KiB regions within - the range (either via a single SFENCE.VMA with _rs1_=`x0`, or with - multiple SFENCE.VMA instructions with _rs1_≠`x0`), then update the PTE(s), as described in <>, unless any inconsistencies are known to be benign. If any inconsistencies do exist, then the effect is the same as when SFENCE.VMA - is used incorrectly: one of the translations will be chosen, but the - choice is unpredictable. - - If an implementation chooses to use a NAPOT PTE (or cached version - thereof), it might not consult the PTE directly specified by the - algorithm in <> at all. Therefore, the D - and A bits may not be identical across all mappings of the same address - range even in typical use cases The operating system must query all - NAPOT aliases of a page to determine whether that page has been accessed - and/or is dirty. If the OS manually sets the A and/or D bits for a page, - it is recommended that the OS also set the A and/or D bits for other - NAPOT aliases as appropriate in order to avoid unnecessary traps. - - Just as with normal PTEs, TLBs are permitted to cache NAPOT PTEs whose V - (Valid) bit is clear. - - Depending on need, the NAPOT scheme may be extended to other - intermediate page sizes and/or to other levels of the page table in the - future. The encoding is designed to accommodate other NAPOT sizes should - that need arise. For example: - - __ - - [%autowidth,float="center",align="center",cols="^,^,<,^",options="header"] - |=== - |i |_pte_._ppn_[_i_] |Description |_pte_.__napot_bits__ - |0 + - 0 + - 0 + - 0 + - 0 + - ... + - 1 + - 1 + - ... - |`x xxxx xxx1` + - `x xxxx xx10` + - `x xxxx x100` + - `x xxxx 1000` + - `x xxx1 0000` + - ... + - `x xxxx xxx1` + - `x xxxx xx10` + - ... - |8 KiB contiguous region + - 16 KiB contiguous region + - 32 KiB contiguous region + - 64 KiB contiguous region + - 128 KiB contiguous region + - ... + - 4 MiB contiguous region + - 8 MiB contiguous region + - ... - | 1 + - 2 + - 3 + - 4 + - 5 + - ... + - 1 + - 2 + - ... - |=== - - In such a case, an implementation may or may not support all options. - The discoverability mechanism for this extension would be extended to - allow system software to determine which sizes are supported. - - Other sizes may remain deliberately excluded, so that PPN bits not being - used to indicate a valid NAPOT region size (e.g., the least-significant - bit of _pte_._ppn_[_i_]) may be repurposed for other uses in the - future. - - However, in case finer-grained intermediate page size support proves not - to be useful, we have chosen to standardize only 64 KiB support as a - first step. - ==== - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2021-11 - requires: - name: Sv39 +$schema: "ext_schema.json#" +kind: extension +name: Svnapot +long_name: Naturally-aligned Power of Two Translation Contiguity +description: | + In Sv39, Sv48, and Sv57, when a PTE has N=1, the PTE represents a + translation that is part of a range of contiguous virtual-to-physical + translations with the same values for PTE bits 5-0. Such ranges must be + of a naturally aligned power-of-2 (NAPOT) granularity larger than the + base page size. + + The Svnapot extension depends on Sv39. + + [[ptenapot]] + .Page table entry encodings when __pte__.N=1 + [%autowidth,float="center",align="center",cols="^,^,<,^",options="header"] + |=== + |i |_pte_._ppn_[_i_] |Description |_pte_.__napot_bits__ + |0 + + 0 + + 0 + + 0 + + 0 + + ≥1 + |`x xxxx xxx1` + + `x xxxx xx1x` + + `x xxxx x1xx` + + `x xxxx 1000` + + `x xxxx 0xxx` + + `x xxxx xxxx` + |_Reserved_ + + _Reserved_ + + _Reserved_ + + 64 KiB contiguous region + + _Reserved_ + + _Reserved_ + | - + + - + + - + + 4 + + - + + - + |=== + + NAPOT PTEs behave identically to non-NAPOT PTEs within the + address-translation algorithm in <>, + except that: + + * If the encoding in _pte_ is valid according to + <>, then instead of returning the original + value of _pte_, implicit reads of a NAPOT PTE return a copy + of _pte_ in which __pte__.__ppn__[__i__][__pte__.__napot_bits__-1:0] is replaced by + __vpn__[__i__][__pte__.__napot_bits__-1:0]. If the encoding in _pte_ is reserved according to + <>, then a page-fault exception must be raised. + * Implicit reads of NAPOT page table entries may create + address-translation cache entries mapping + _a_ + _j_*PTESIZE to a copy of _pte_ in which _pte_._ppn_[_i_][_pte_.__napot_bits__-1:0] + is replaced by _vpn[i][pte.napot_bits_-1:0], for any or all _j_ such that + __j__ >> __napot_bits__ = __vpn__[__i__] >> __napot_bits__, all for the address space identified in _satp_ as loaded by step 1. + + [NOTE] + ==== + The motivation for a NAPOT PTE is that it can be cached in a TLB as one + or more entries representing the contiguous region as if it were a + single (large) page covered by a single translation. This compaction can + help relieve TLB pressure in some scenarios. The encoding is designed to + fit within the pre-existing Sv39, Sv48, and Sv57 PTE formats so as not + to disrupt existing implementations or designs that choose not to + implement the scheme. It is also designed so as not to complicate the + definition of the address-translation algorithm. + + The address translation cache abstraction captures the behavior that + would result from the creation of a single TLB entry covering the entire + NAPOT region. It is also designed to be consistent with implementations + that support NAPOT PTEs by splitting the NAPOT region into TLB entries + covering any smaller power-of-two region sizes. For example, a 64 KiB + NAPOT PTE might trigger the creation of 16 standard 4 KiB TLB entries, + all with contents generated from the NAPOT PTE (even if the PTEs for the + other 4 KiB regions have different contents). + + In typical usage scenarios, NAPOT PTEs in the same region will have the + same attributes, same PPNs, and same values for bits 5-0. RSW remains + reserved for supervisor software control. It is the responsibility of + the OS and/or hypervisor to configure the page tables in such a way that + there are no inconsistencies between NAPOT PTEs and other NAPOT or + non-NAPOT PTEs that overlap the same address range. If an update needs + to be made, the OS generally should first mark all of the PTEs invalid, + then issue SFENCE.VMA instruction(s) covering all 4 KiB regions within + the range (either via a single SFENCE.VMA with _rs1_=`x0`, or with + multiple SFENCE.VMA instructions with _rs1_≠`x0`), then update the PTE(s), as described in <>, unless any inconsistencies are known to be benign. If any inconsistencies do exist, then the effect is the same as when SFENCE.VMA + is used incorrectly: one of the translations will be chosen, but the + choice is unpredictable. + + If an implementation chooses to use a NAPOT PTE (or cached version + thereof), it might not consult the PTE directly specified by the + algorithm in <> at all. Therefore, the D + and A bits may not be identical across all mappings of the same address + range even in typical use cases The operating system must query all + NAPOT aliases of a page to determine whether that page has been accessed + and/or is dirty. If the OS manually sets the A and/or D bits for a page, + it is recommended that the OS also set the A and/or D bits for other + NAPOT aliases as appropriate in order to avoid unnecessary traps. + + Just as with normal PTEs, TLBs are permitted to cache NAPOT PTEs whose V + (Valid) bit is clear. + + Depending on need, the NAPOT scheme may be extended to other + intermediate page sizes and/or to other levels of the page table in the + future. The encoding is designed to accommodate other NAPOT sizes should + that need arise. For example: + + __ + + [%autowidth,float="center",align="center",cols="^,^,<,^",options="header"] + |=== + |i |_pte_._ppn_[_i_] |Description |_pte_.__napot_bits__ + |0 + + 0 + + 0 + + 0 + + 0 + + ... + + 1 + + 1 + + ... + |`x xxxx xxx1` + + `x xxxx xx10` + + `x xxxx x100` + + `x xxxx 1000` + + `x xxx1 0000` + + ... + + `x xxxx xxx1` + + `x xxxx xx10` + + ... + |8 KiB contiguous region + + 16 KiB contiguous region + + 32 KiB contiguous region + + 64 KiB contiguous region + + 128 KiB contiguous region + + ... + + 4 MiB contiguous region + + 8 MiB contiguous region + + ... + | 1 + + 2 + + 3 + + 4 + + 5 + + ... + + 1 + + 2 + + ... + |=== + + In such a case, an implementation may or may not support all options. + The discoverability mechanism for this extension would be extended to + allow system software to determine which sizes are supported. + + Other sizes may remain deliberately excluded, so that PPN bits not being + used to indicate a valid NAPOT region size (e.g., the least-significant + bit of _pte_._ppn_[_i_]) may be repurposed for other uses in the + future. + + However, in case finer-grained intermediate page size support proves not + to be useful, we have chosen to standardize only 64 KiB support as a + first step. + ==== +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2021-11 + requires: + name: Sv39 diff --git a/arch/ext/Svpbmt.yaml b/arch/ext/Svpbmt.yaml index 7d3b6abb9..43db85e29 100644 --- a/arch/ext/Svpbmt.yaml +++ b/arch/ext/Svpbmt.yaml @@ -1,21 +1,23 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Svpbmt: - long_name: Page-based memory types - description: | - This extension mandates that the `satp` mode Bare must - be supported. +$schema: "ext_schema.json#" +kind: extension +name: Svpbmt +long_name: Page-based memory types +description: | + This extension mandates that the `satp` mode Bare must + be supported. - [NOTE] - This extension was ratified as part of the RVA22 profile. - type: privileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: null - requires: - name: Sv39 - param_constraints: - SATP_MODE_BARE: - schema: - const: true + [NOTE] + This extension was ratified as part of the RVA22 profile. +type: privileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: null + requires: + name: Sv39 + param_constraints: + SATP_MODE_BARE: + schema: + const: true diff --git a/arch/ext/U.yaml b/arch/ext/U.yaml index 0470a3eb8..c7c4fc253 100644 --- a/arch/ext/U.yaml +++ b/arch/ext/U.yaml @@ -1,48 +1,50 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -U: - long_name: User-level privilege mode - description: User-level privilege mode - type: privileged - versions: - - version: "1.12.0" - state: ratified - ratification_date: 2019-12 - params: - MUTABLE_MISA_U: - description: | - Indicates whether or not the `U` extension can be disabled with the `misa.U` bit. - schema: - type: boolean - U_MODE_ENDIANESS: - description: | - Endianess of data in U-mode. Can be one of: +$schema: "ext_schema.json#" +kind: extension +name: U +long_name: User-level privilege mode +description: User-level privilege mode +type: privileged +versions: +- version: "1.12.0" + state: ratified + ratification_date: 2019-12 +params: + MUTABLE_MISA_U: + description: | + Indicates whether or not the `U` extension can be disabled with the `misa.U` bit. + schema: + type: boolean + U_MODE_ENDIANESS: + description: | + Endianess of data in U-mode. Can be one of: - * little: M-mode data is always little endian - * big: M-mode data is always big endian - * dynamic: M-mode data can be either little or big endian, - depending on the CSR field `mstatus.UBE` - schema: - type: string - enum: [little, big, dynamic] - UXLEN: - description: | - Set of XLENs supported in U-mode. Can be one of: + * little: M-mode data is always little endian + * big: M-mode data is always big endian + * dynamic: M-mode data can be either little or big endian, + depending on the CSR field `mstatus.UBE` + schema: + type: string + enum: [little, big, dynamic] + UXLEN: + description: | + Set of XLENs supported in U-mode. Can be one of: - * 32: SXLEN is always 32 - * 64: SXLEN is always 64 - * 3264: SXLEN can be changed (via mstatus.UXL) between 32 and 64 - schema: - type: integer - enum: [32, 64, 3264] - extra_validation: | - assert UXLEN == 32 if XLEN == 32 - TRAP_ON_ECALL_FROM_U: - description: | - Whether or not an ECALL-from-U-mode causes a synchronous exception. + * 32: SXLEN is always 32 + * 64: SXLEN is always 64 + * 3264: SXLEN can be changed (via mstatus.UXL) between 32 and 64 + schema: + type: integer + enum: [32, 64, 3264] + extra_validation: | + assert UXLEN == 32 if XLEN == 32 + TRAP_ON_ECALL_FROM_U: + description: | + Whether or not an ECALL-from-U-mode causes a synchronous exception. - The spec states that implementations may handle ECALLs transparently - without raising a trap, in which case the EEI must provide a builtin. - schema: - type: boolean - default: true \ No newline at end of file + The spec states that implementations may handle ECALLs transparently + without raising a trap, in which case the EEI must provide a builtin. + schema: + type: boolean + default: true \ No newline at end of file diff --git a/arch/ext/V.yaml b/arch/ext/V.yaml index 3afdb311f..e40290605 100644 --- a/arch/ext/V.yaml +++ b/arch/ext/V.yaml @@ -1,47 +1,49 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -V: - type: unprivileged - long_name: Variable-length vector - versions: - - version: "1.0.0" - state: ratified - ratification_date: null - description: | - TODO - params: - MUTABLE_MISA_V: - description: | - Indicates whether or not the `V` extension can be disabled with the `misa.V` bit. - schema: - type: boolean - HW_MSTATUS_VS_DIRTY_UPDATE: - description: | - Indicates whether or not hardware will write to `mstatus.VS` +$schema: "ext_schema.json#" +kind: extension +name: V +type: unprivileged +long_name: Variable-length vector +versions: +- version: "1.0.0" + state: ratified + ratification_date: null +description: | + TODO +params: + MUTABLE_MISA_V: + description: | + Indicates whether or not the `V` extension can be disabled with the `misa.V` bit. + schema: + type: boolean + HW_MSTATUS_VS_DIRTY_UPDATE: + description: | + Indicates whether or not hardware will write to `mstatus.VS` - Values are: - [separator="!"] - !=== - h! never ! Hardware never writes `mstatus.VS` - h! precise ! Hardware writes `mstatus.VS` to the Dirty (3) state precisely when V registers are modified - h! imprecise ! Hardware writes `mstatus.VS` imprecisely. This will result in a call to unpredictable() on any attempt to read `mstatus` or write vector state. - !=== - schema: - type: string - enum: ["never", "precise", "imprecise"] - MSTATUS_VS_LEGAL_VALUES: - description: | - The set of values that mstatus.VS will accept from a software write. - schema: - type: array - items: - type: integer - enum: [0,1,2,3] - maxItems: 4 - uniqueItems: true - also_defined_in: S - extra_validation: | - assert MSTATUS_VS_LEGAL_VALUES.include?(0) && MSTATUS_VS_LEGAL_VALUES.include?(3) if ext?(:V) + Values are: + [separator="!"] + !=== + h! never ! Hardware never writes `mstatus.VS` + h! precise ! Hardware writes `mstatus.VS` to the Dirty (3) state precisely when V registers are modified + h! imprecise ! Hardware writes `mstatus.VS` imprecisely. This will result in a call to unpredictable() on any attempt to read `mstatus` or write vector state. + !=== + schema: + type: string + enum: ["never", "precise", "imprecise"] + MSTATUS_VS_LEGAL_VALUES: + description: | + The set of values that mstatus.VS will accept from a software write. + schema: + type: array + items: + type: integer + enum: [0,1,2,3] + maxItems: 4 + uniqueItems: true + also_defined_in: S + extra_validation: | + assert MSTATUS_VS_LEGAL_VALUES.include?(0) && MSTATUS_VS_LEGAL_VALUES.include?(3) if ext?(:V) - # 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") \ No newline at end of file + # 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") \ No newline at end of file diff --git a/arch/ext/Za128rs.yaml b/arch/ext/Za128rs.yaml index 4b802cc2d..e78da5e68 100644 --- a/arch/ext/Za128rs.yaml +++ b/arch/ext/Za128rs.yaml @@ -1,25 +1,26 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Za128rs: - name: Maximum 128-byte reservation sets - long_name: Reservation set requirement for RVA profiles - description: | - Reservation sets must be contiguous, naturally aligned, and at most 128 bytes in size. +$schema: "ext_schema.json#" +kind: extension +name: Za128rs +long_name: Reservation set requirement for RVA profiles +description: | + Reservation sets must be contiguous, naturally aligned, and at most 128 bytes in size. - [NOTE] - This extension was ratified as part of the RVA20 profile. + [NOTE] + This extension was ratified as part of the RVA20 profile. - [NOTE] - The minimum reservation set size is effectively determined by the size of atomic accesses in - the A extension. - versions: - - version: "1.0.0" - state: ratified - ratification_date: null - param_constraints: - LRSC_RESERVATION_STRATEGY: - schema: - oneOf: - - const: reserve exactly enough to cover the access - - const: reserve naturally-aligned 64-byte region - - const: reserve naturally-aligned 128-byte region + [NOTE] + The minimum reservation set size is effectively determined by the size of atomic accesses in + the A extension. +versions: +- version: "1.0.0" + state: ratified + ratification_date: null + param_constraints: + LRSC_RESERVATION_STRATEGY: + schema: + oneOf: + - const: reserve exactly enough to cover the access + - const: reserve naturally-aligned 64-byte region + - const: reserve naturally-aligned 128-byte region diff --git a/arch/ext/Zaamo.yaml b/arch/ext/Zaamo.yaml index c5b07d9ab..84722a566 100644 --- a/arch/ext/Zaamo.yaml +++ b/arch/ext/Zaamo.yaml @@ -1,131 +1,133 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zaamo: - long_name: Load-acquire/Store-release atomic instructions - type: unprivileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2024-04 - description: | - The atomic memory operation (AMO) instructions perform read-modify-write - operations for multiprocessor synchronization and are encoded with an - R-type instruction format. These AMO instructions atomically load a data - value from the address in _rs1_, place the value into register _rd_, - apply a binary operator to the loaded value and the original value in - _rs2_, then store the result back to the original address in _rs1_. AMOs - can either operate on _doublewords_ (RV64 only) or _words_ in memory. For - RV64, 32-bit AMOs always sign-extend the value placed in _rd_, and - ignore the upper 32 bits of the original value of _rs2_. +$schema: "ext_schema.json#" +kind: extension +name: Zaamo +long_name: Load-acquire/Store-release atomic instructions +type: unprivileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2024-04 +description: | + The atomic memory operation (AMO) instructions perform read-modify-write + operations for multiprocessor synchronization and are encoded with an + R-type instruction format. These AMO instructions atomically load a data + value from the address in _rs1_, place the value into register _rd_, + apply a binary operator to the loaded value and the original value in + _rs2_, then store the result back to the original address in _rs1_. AMOs + can either operate on _doublewords_ (RV64 only) or _words_ in memory. For + RV64, 32-bit AMOs always sign-extend the value placed in _rd_, and + ignore the upper 32 bits of the original value of _rs2_. - For AMOs, the `Zaamo` extension requires that the address held in _rs1_ be - naturally aligned to the size of the operand (i.e., eight-byte aligned - for _doublewords_ and four-byte aligned for _words_). If the address - is not naturally aligned, an address-misaligned exception or an - access-fault exception will be generated. The access-fault exception can - be generated for a memory access that would otherwise be able to - complete except for the misalignment, if the misaligned access should - not be emulated. + For AMOs, the `Zaamo` extension requires that the address held in _rs1_ be + naturally aligned to the size of the operand (i.e., eight-byte aligned + for _doublewords_ and four-byte aligned for _words_). If the address + is not naturally aligned, an address-misaligned exception or an + access-fault exception will be generated. The access-fault exception can + be generated for a memory access that would otherwise be able to + complete except for the misalignment, if the misaligned access should + not be emulated. - The misaligned atomicity granule PMA, defined in Volume II of this manual, - optionally relaxes this alignment requirement. - If present, the misaligned atomicity granule PMA specifies the size - of a misaligned atomicity granule, a power-of-two number of bytes. - The misaligned atomicity granule PMA applies only to AMOs, loads and stores - defined in the base ISAs, and loads and stores of no more than XLEN bits - defined in the F, D, and Q extensions. - For an instruction in that set, if all accessed bytes lie within the same - misaligned atomicity granule, the instruction will not raise an exception for - reasons of address alignment, and the instruction will give rise to only one - memory operation for the purposes of RVWMO--i.e., it will execute atomically. + The misaligned atomicity granule PMA, defined in Volume II of this manual, + optionally relaxes this alignment requirement. + If present, the misaligned atomicity granule PMA specifies the size + of a misaligned atomicity granule, a power-of-two number of bytes. + The misaligned atomicity granule PMA applies only to AMOs, loads and stores + defined in the base ISAs, and loads and stores of no more than XLEN bits + defined in the F, D, and Q extensions. + For an instruction in that set, if all accessed bytes lie within the same + misaligned atomicity granule, the instruction will not raise an exception for + reasons of address alignment, and the instruction will give rise to only one + memory operation for the purposes of RVWMO--i.e., it will execute atomically. - The operations supported are swap, integer add, bitwise AND, bitwise OR, - bitwise XOR, and signed and unsigned integer maximum and minimum. - Without ordering constraints, these AMOs can be used to implement - parallel reduction operations, where typically the return value would be - discarded by writing to `x0`. + The operations supported are swap, integer add, bitwise AND, bitwise OR, + bitwise XOR, and signed and unsigned integer maximum and minimum. + Without ordering constraints, these AMOs can be used to implement + parallel reduction operations, where typically the return value would be + discarded by writing to `x0`. - [NOTE] - ==== - We provided fetch-and-op style atomic primitives as they scale to highly - parallel systems better than LR/SC or CAS. A simple microarchitecture - can implement AMOs using the LR/SC primitives, provided the - implementation can guarantee the AMO eventually completes. More complex - implementations might also implement AMOs at memory controllers, and can - optimize away fetching the original value when the destination is `x0`. + [NOTE] + ==== + We provided fetch-and-op style atomic primitives as they scale to highly + parallel systems better than LR/SC or CAS. A simple microarchitecture + can implement AMOs using the LR/SC primitives, provided the + implementation can guarantee the AMO eventually completes. More complex + implementations might also implement AMOs at memory controllers, and can + optimize away fetching the original value when the destination is `x0`. - The set of AMOs was chosen to support the C11/C++11 atomic memory - operations efficiently, and also to support parallel reductions in - memory. Another use of AMOs is to provide atomic updates to - memory-mapped device registers (e.g., setting, clearing, or toggling - bits) in the I/O space. + The set of AMOs was chosen to support the C11/C++11 atomic memory + operations efficiently, and also to support parallel reductions in + memory. Another use of AMOs is to provide atomic updates to + memory-mapped device registers (e.g., setting, clearing, or toggling + bits) in the I/O space. - The Zaamo extension enables microcontroller class implementations to utilize - atomic primitives from the AMO subset of the A extension. Typically such - implementations do not have caches and thus may not be able to naturally support - the LR/SC instructions provided by the Zalrsc extension. - ==== + The Zaamo extension enables microcontroller class implementations to utilize + atomic primitives from the AMO subset of the A extension. Typically such + implementations do not have caches and thus may not be able to naturally support + the LR/SC instructions provided by the Zalrsc extension. + ==== - To help implement multiprocessor synchronization, the AMOs optionally - provide release consistency semantics. If the _aq_ bit is set, then no - later memory operations in this RISC-V hart can be observed to take - place before the AMO. Conversely, if the _rl_ bit is set, then other - RISC-V harts will not observe the AMO before memory accesses preceding - the AMO in this RISC-V hart. Setting both the _aq_ and the _rl_ bit on - an AMO makes the sequence sequentially consistent, meaning that it - cannot be reordered with earlier or later memory operations from the - same hart. + To help implement multiprocessor synchronization, the AMOs optionally + provide release consistency semantics. If the _aq_ bit is set, then no + later memory operations in this RISC-V hart can be observed to take + place before the AMO. Conversely, if the _rl_ bit is set, then other + RISC-V harts will not observe the AMO before memory accesses preceding + the AMO in this RISC-V hart. Setting both the _aq_ and the _rl_ bit on + an AMO makes the sequence sequentially consistent, meaning that it + cannot be reordered with earlier or later memory operations from the + same hart. - [NOTE] - ==== - The AMOs were designed to implement the C11 and C++11 memory models - efficiently. Although the FENCE R, RW instruction suffices to implement - the _acquire_ operation and FENCE RW, W suffices to implement _release_, - both imply additional unnecessary ordering as compared to AMOs with the - corresponding _aq_ or _rl_ bit set. - ==== + [NOTE] + ==== + The AMOs were designed to implement the C11 and C++11 memory models + efficiently. Although the FENCE R, RW instruction suffices to implement + the _acquire_ operation and FENCE RW, W suffices to implement _release_, + both imply additional unnecessary ordering as compared to AMOs with the + corresponding _aq_ or _rl_ bit set. + ==== - An example code sequence for a critical section guarded by a - test-and-test-and-set spinlock is shown in - Example <>. Note the first AMO is marked _aq_ to - order the lock acquisition before the critical section, and the second - AMO is marked _rl_ to order the critical section before the lock - relinquishment. + An example code sequence for a critical section guarded by a + test-and-test-and-set spinlock is shown in + Example <>. Note the first AMO is marked _aq_ to + order the lock acquisition before the critical section, and the second + AMO is marked _rl_ to order the critical section before the lock + relinquishment. - <<< + <<< - [[critical]] - [source,asm] - .Sample code for mutual exclusion. `a0` contains the address of the lock. - li t0, 1 # Initialize swap value. - again: - lw t1, (a0) # Check if lock is held. - bnez t1, again # Retry if held. - amoswap.w.aq t1, t0, (a0) # Attempt to acquire lock. - bnez t1, again # Retry if held. - # ... - # Critical section. - # ... - amoswap.w.rl x0, x0, (a0) # Release lock by storing 0. + [[critical]] + [source,asm] + .Sample code for mutual exclusion. `a0` contains the address of the lock. + li t0, 1 # Initialize swap value. + again: + lw t1, (a0) # Check if lock is held. + bnez t1, again # Retry if held. + amoswap.w.aq t1, t0, (a0) # Attempt to acquire lock. + bnez t1, again # Retry if held. + # ... + # Critical section. + # ... + amoswap.w.rl x0, x0, (a0) # Release lock by storing 0. - [NOTE] - ==== - We recommend the use of the AMO Swap idiom shown above for both lock - acquire and release to simplify the implementation of speculative lock - elision. cite:[Rajwar:2001:SLE] - ==== + [NOTE] + ==== + We recommend the use of the AMO Swap idiom shown above for both lock + acquire and release to simplify the implementation of speculative lock + elision. cite:[Rajwar:2001:SLE] + ==== - [NOTE] - ==== - The instructions in the `A` extension can be used to provide sequentially - consistent loads and stores, but this constrains hardware - reordering of memory accesses more than necessary. - A C++ sequentially consistent load can be implemented as - an LR with _aq_ set. However, the LR/SC eventual - success guarantee may slow down concurrent loads from the same effective - address. A sequentially consistent store can be implemented as an AMOSWAP - that writes the old value to `x0` and has _rl_ set. However the superfluous - load may impose ordering constraints that are unnecessary for this use case. - Specific compilation conventions may require both the _aq_ and _rl_ - bits to be set in either or both the LR and AMOSWAP instructions. - ==== + [NOTE] + ==== + The instructions in the `A` extension can be used to provide sequentially + consistent loads and stores, but this constrains hardware + reordering of memory accesses more than necessary. + A C++ sequentially consistent load can be implemented as + an LR with _aq_ set. However, the LR/SC eventual + success guarantee may slow down concurrent loads from the same effective + address. A sequentially consistent store can be implemented as an AMOSWAP + that writes the old value to `x0` and has _rl_ set. However the superfluous + load may impose ordering constraints that are unnecessary for this use case. + Specific compilation conventions may require both the _aq_ and _rl_ + bits to be set in either or both the LR and AMOSWAP instructions. + ==== diff --git a/arch/ext/Zalrsc.yaml b/arch/ext/Zalrsc.yaml index 3f6a07fbc..d2d0da35f 100644 --- a/arch/ext/Zalrsc.yaml +++ b/arch/ext/Zalrsc.yaml @@ -1,311 +1,313 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zalrsc: - long_name: Atomic read-modify-write instructions - type: unprivileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2024-04 - description: | - - Complex atomic memory operations on a single memory word or doubleword - are performed with the load-reserved (LR) and store-conditional (SC) - instructions. `LR.W` loads a word from the address in _rs1_, places the - sign-extended value in _rd_, and registers a _reservation set_--a set of - bytes that subsumes the bytes in the addressed word. `SC.W` conditionally - writes a word in _rs2_ to the address in _rs1_: the `SC.W` succeeds only - if the reservation is still valid and the reservation set contains the - bytes being written. If the `SC.W` succeeds, the instruction writes the - word in _rs2_ to memory, and it writes zero to _rd_. If the `SC.W` fails, - the instruction does not write to memory, and it writes a nonzero value - to _rd_. For the purposes of memory protection, a failed `SC.W` may be - treated like a store. Regardless of success or failure, executing an - `SC.W` instruction invalidates any reservation held by this hart. `LR.D` and - `SC.D` act analogously on doublewords and are only available on RV64. For - RV64, `LR.W` and `SC.W` sign-extend the value placed in _rd_. - - [NOTE] - ==== - Both compare-and-swap (CAS) and LR/SC can be used to build lock-free - data structures. After extensive discussion, we opted for LR/SC for - several reasons: 1) CAS suffers from the ABA problem, which LR/SC avoids - because it monitors all writes to the address rather than only checking - for changes in the data value; 2) CAS would also require a new integer - instruction format to support three source operands (address, compare - value, swap value) as well as a different memory system message format, - which would complicate microarchitectures; 3) Furthermore, to avoid the - ABA problem, other systems provide a double-wide CAS (DW-CAS) to allow a - counter to be tested and incremented along with a data word. This - requires reading five registers and writing two in one instruction, and - also a new larger memory system message type, further complicating - implementations; 4) LR/SC provides a more efficient implementation of - many primitives as it only requires one load as opposed to two with CAS - (one load before the CAS instruction to obtain a value for speculative - computation, then a second load as part of the CAS instruction to check - if value is unchanged before updating). - - The main disadvantage of LR/SC over CAS is livelock, which we avoid, - under certain circumstances, with an architected guarantee of eventual - forward progress as described below. Another concern is whether the - influence of the current x86 architecture, with its DW-CAS, will - complicate porting of synchronization libraries and other software that - assumes DW-CAS is the basic machine primitive. A possible mitigating - factor is the recent addition of transactional memory instructions to - x86, which might cause a move away from DW-CAS. - - More generally, a multi-word atomic primitive is desirable, but there is - still considerable debate about what form this should take, and - guaranteeing forward progress adds complexity to a system. - ==== - - [NOTE] - ==== - Note on the above note -- RISC-V now has CAS (Zacas)!! - ==== - - The failure code with value 1 encodes an unspecified failure. Other - failure codes are reserved at this time. Portable software should only - assume the failure code will be non-zero. - - [NOTE] - ==== - We reserve a failure code of 1 to mean ''unspecified'' so that simple - implementations may return this value using the existing mux required - for the `SLT`/`SLTU` instructions. More specific failure codes might be - defined in future versions or extensions to the ISA. - ==== - - For LR and SC, the `Zalrsc` extension requires that the address held in _rs1_ - be naturally aligned to the size of the operand (i.e., eight-byte - aligned for _doublewords_ and four-byte aligned for _words_). If the - address is not naturally aligned, an address-misaligned exception or an - access-fault exception will be generated. The access-fault exception can - be generated for a memory access that would otherwise be able to - complete except for the misalignment, if the misaligned access should - not be emulated. - [NOTE] - ==== - Emulating misaligned LR/SC sequences is impractical in most systems. - - Misaligned LR/SC sequences also raise the possibility of accessing - multiple reservation sets at once, which present definitions do not - provide for. - ==== - - An implementation can register an arbitrarily large reservation set on - each LR, provided the reservation set includes all bytes of the - addressed data word or doubleword. An SC can only pair with the most - recent LR in program order. An SC may succeed only if no store from - another hart to the reservation set can be observed to have occurred - between the LR and the SC, and if there is no other SC between the LR - and itself in program order. An SC may succeed only if no write from a - device other than a hart to the bytes accessed by the LR instruction can - be observed to have occurred between the LR and SC. Note this LR might - have had a different effective address and data size, but reserved the - SC's address as part of the reservation set. - - [NOTE] - ==== - Following this model, in systems with memory translation, an SC is - allowed to succeed if the earlier LR reserved the same location using an - alias with a different virtual address, but is also allowed to fail if - the virtual address is different. - - To accommodate legacy devices and buses, writes from devices other than - RISC-V harts are only required to invalidate reservations when they - overlap the bytes accessed by the LR. These writes are not required to - invalidate the reservation when they access other bytes in the - reservation set. - ==== - - The SC must fail if the address is not within the reservation set of the - most recent LR in program order. The SC must fail if a store to the - reservation set from another hart can be observed to occur between the - LR and SC. The SC must fail if a write from some other device to the - bytes accessed by the LR can be observed to occur between the LR and SC. - (If such a device writes the reservation set but does not write the - bytes accessed by the LR, the SC may or may not fail.) An SC must fail - if there is another SC (to any address) between the LR and the SC in - program order. The precise statement of the atomicity requirements for - successful LR/SC sequences is defined by the Atomicity Axiom in - <>. - - [NOTE] - ==== - The platform should provide a means to determine the size and shape of - the reservation set. - - A platform specification may constrain the size and shape of the - reservation set. - - A store-conditional instruction to a scratch word of memory should be - used to forcibly invalidate any existing load reservation: - - * during a preemptive context switch, and - * if necessary when changing virtual to physical address mappings, such - as when migrating pages that might contain an active reservation. - - The invalidation of a hart's reservation when it executes an LR or SC - imply that a hart can only hold one reservation at a time, and that an - SC can only pair with the most recent LR, and LR with the next following - SC, in program order. This is a restriction to the Atomicity Axiom in - <> that ensures software runs correctly on - expected common implementations that operate in this manner. - ==== - - An SC instruction can never be observed by another RISC-V hart before - the LR instruction that established the reservation. - - [NOTE] - ==== - The LR/SC sequence - can be given acquire semantics by setting the _aq_ bit on the LR - instruction. The LR/SC sequence can be given release semantics by - by setting the _rl_ bit on the SC instruction. Assuming - suitable mappings for other atomic operations, setting the - _aq_ bit on the LR instruction, and setting the - _rl_ bit on the SC instruction makes the LR/SC - sequence sequentially consistent in the C\++ `memory_order_seq_cst` - sense. Such a sequence does not act as a fence for ordering ordinary - load and store instructions before and after the sequence. Specific - instruction mappings for other C++ atomic operations, - or stronger notions of "sequential consistency", may require both - bits to be set on either or both of the LR or SC instruction. - - If neither bit is set on either LR or SC, the LR/SC sequence can be - observed to occur before or after surrounding memory operations from the - same RISC-V hart. This can be appropriate when the LR/SC sequence is - used to implement a parallel reduction operation. - ==== - - Software should not set the _rl_ bit on an LR instruction unless the - _aq_ bit is also set, nor should software set the _aq_ bit on an SC - instruction unless the _rl_ bit is also set. LR._rl_ and SC._aq_ - instructions are not guaranteed to provide any stronger ordering than - those with both bits clear, but may result in lower performance. - - <<< - - [[cas]] - [source,asm] - .Sample code for compare-and-swap function using LR/SC. - # a0 holds address of memory location - # a1 holds expected value - # a2 holds desired value - # a0 holds return value, 0 if successful, !0 otherwise - cas: - lr.w t0, (a0) # Load original value. - bne t0, a1, fail # Doesn't match, so fail. - sc.w t0, a2, (a0) # Try to update. - bnez t0, cas # Retry if store-conditional failed. - li a0, 0 # Set return to success. - jr ra # Return. - fail: - li a0, 1 # Set return to failure. - jr ra # Return. - - LR/SC can be used to construct lock-free data structures. An example - using LR/SC to implement a compare-and-swap function is shown in - <>. If inlined, compare-and-swap functionality need only take four instructions. - - [[sec:lrscseq]] - === Eventual Success of Store-Conditional Instructions - - The `Zalrsc` extension defines _constrained LR/SC loops_, which have - the following properties: - - * The loop comprises only an LR/SC sequence and code to retry the - sequence in the case of failure, and must comprise at most 16 - instructions placed sequentially in memory. - * An LR/SC sequence begins with an LR instruction and ends with an SC - instruction. The dynamic code executed between the LR and SC - instructions can only contain instructions from the base ''I'' - instruction set, excluding loads, stores, backward jumps, taken backward - branches, JALR, FENCE, and SYSTEM instructions. If the ''C'' extension - is supported, then compressed forms of the aforementioned ''I'' - instructions are also permitted. - * The code to retry a failing LR/SC sequence can contain backwards jumps - and/or branches to repeat the LR/SC sequence, but otherwise has the same - constraint as the code between the LR and SC. - * The LR and SC addresses must lie within a memory region with the - _LR/SC eventuality_ property. The execution environment is responsible - for communicating which regions have this property. - * The SC must be to the same effective address and of the same data size - as the latest LR executed by the same hart. - - LR/SC sequences that do not lie within constrained LR/SC loops are - _unconstrained_. Unconstrained LR/SC sequences might succeed on some - attempts on some implementations, but might never succeed on other - implementations. - - [NOTE] - ==== - We restricted the length of LR/SC loops to fit within 64 contiguous - instruction bytes in the base ISA to avoid undue restrictions on - instruction cache and TLB size and associativity. Similarly, we - disallowed other loads and stores within the loops to avoid restrictions - on data-cache associativity in simple implementations that track the - reservation within a private cache. The restrictions on branches and - jumps limit the time that can be spent in the sequence. Floating-point - operations and integer multiply/divide were disallowed to simplify the - operating system's emulation of these instructions on implementations - lacking appropriate hardware support. - - Software is not forbidden from using unconstrained LR/SC sequences, but - portable software must detect the case that the sequence repeatedly - fails, then fall back to an alternate code sequence that does not rely - on an unconstrained LR/SC sequence. Implementations are permitted to - unconditionally fail any unconstrained LR/SC sequence. - ==== - - If a hart _H_ enters a constrained LR/SC loop, the execution environment - must guarantee that one of the following events eventually occurs: - - * _H_ or some other hart executes a successful SC to the reservation set - of the LR instruction in _H_'s constrained LR/SC loops. - * Some other hart executes an unconditional store or AMO instruction to - the reservation set of the LR instruction in _H_'s constrained LR/SC - loop, or some other device in the system writes to that reservation set. - * _H_ executes a branch or jump that exits the constrained LR/SC loop. - * _H_ traps. - - [NOTE] - ==== - Note that these definitions permit an implementation to fail an SC - instruction occasionally for any reason, provided the aforementioned - guarantee is not violated. - - As a consequence of the eventuality guarantee, if some harts in an - execution environment are executing constrained LR/SC loops, and no - other harts or devices in the execution environment execute an - unconditional store or AMO to that reservation set, then at least one - hart will eventually exit its constrained LR/SC loop. By contrast, if - other harts or devices continue to write to that reservation set, it is - not guaranteed that any hart will exit its LR/SC loop. - - Loads and load-reserved instructions do not by themselves impede the - progress of other harts' LR/SC sequences. We note this constraint - implies, among other things, that loads and load-reserved instructions - executed by other harts (possibly within the same core) cannot impede - LR/SC progress indefinitely. For example, cache evictions caused by - another hart sharing the cache cannot impede LR/SC progress - indefinitely. Typically, this implies reservations are tracked - independently of evictions from any shared cache. Similarly, cache - misses caused by speculative execution within a hart cannot impede LR/SC - progress indefinitely. - - These definitions admit the possibility that SC instructions may - spuriously fail for implementation reasons, provided progress is - eventually made. - - One advantage of CAS is that it guarantees that some hart eventually - makes progress, whereas an LR/SC atomic sequence could livelock - indefinitely on some systems. To avoid this concern, we added an - architectural guarantee of livelock freedom for certain LR/SC sequences. - - Earlier versions of this specification imposed a stronger - starvation-freedom guarantee. However, the weaker livelock-freedom - guarantee is sufficient to implement the C11 and C++11 languages, and is - substantially easier to provide in some microarchitectural styles. - ==== \ No newline at end of file +$schema: "ext_schema.json#" +kind: extension +name: Zalrsc +long_name: Atomic read-modify-write instructions +type: unprivileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2024-04 +description: | + + Complex atomic memory operations on a single memory word or doubleword + are performed with the load-reserved (LR) and store-conditional (SC) + instructions. `LR.W` loads a word from the address in _rs1_, places the + sign-extended value in _rd_, and registers a _reservation set_--a set of + bytes that subsumes the bytes in the addressed word. `SC.W` conditionally + writes a word in _rs2_ to the address in _rs1_: the `SC.W` succeeds only + if the reservation is still valid and the reservation set contains the + bytes being written. If the `SC.W` succeeds, the instruction writes the + word in _rs2_ to memory, and it writes zero to _rd_. If the `SC.W` fails, + the instruction does not write to memory, and it writes a nonzero value + to _rd_. For the purposes of memory protection, a failed `SC.W` may be + treated like a store. Regardless of success or failure, executing an + `SC.W` instruction invalidates any reservation held by this hart. `LR.D` and + `SC.D` act analogously on doublewords and are only available on RV64. For + RV64, `LR.W` and `SC.W` sign-extend the value placed in _rd_. + + [NOTE] + ==== + Both compare-and-swap (CAS) and LR/SC can be used to build lock-free + data structures. After extensive discussion, we opted for LR/SC for + several reasons: 1) CAS suffers from the ABA problem, which LR/SC avoids + because it monitors all writes to the address rather than only checking + for changes in the data value; 2) CAS would also require a new integer + instruction format to support three source operands (address, compare + value, swap value) as well as a different memory system message format, + which would complicate microarchitectures; 3) Furthermore, to avoid the + ABA problem, other systems provide a double-wide CAS (DW-CAS) to allow a + counter to be tested and incremented along with a data word. This + requires reading five registers and writing two in one instruction, and + also a new larger memory system message type, further complicating + implementations; 4) LR/SC provides a more efficient implementation of + many primitives as it only requires one load as opposed to two with CAS + (one load before the CAS instruction to obtain a value for speculative + computation, then a second load as part of the CAS instruction to check + if value is unchanged before updating). + + The main disadvantage of LR/SC over CAS is livelock, which we avoid, + under certain circumstances, with an architected guarantee of eventual + forward progress as described below. Another concern is whether the + influence of the current x86 architecture, with its DW-CAS, will + complicate porting of synchronization libraries and other software that + assumes DW-CAS is the basic machine primitive. A possible mitigating + factor is the recent addition of transactional memory instructions to + x86, which might cause a move away from DW-CAS. + + More generally, a multi-word atomic primitive is desirable, but there is + still considerable debate about what form this should take, and + guaranteeing forward progress adds complexity to a system. + ==== + + [NOTE] + ==== + Note on the above note -- RISC-V now has CAS (Zacas)!! + ==== + + The failure code with value 1 encodes an unspecified failure. Other + failure codes are reserved at this time. Portable software should only + assume the failure code will be non-zero. + + [NOTE] + ==== + We reserve a failure code of 1 to mean ''unspecified'' so that simple + implementations may return this value using the existing mux required + for the `SLT`/`SLTU` instructions. More specific failure codes might be + defined in future versions or extensions to the ISA. + ==== + + For LR and SC, the `Zalrsc` extension requires that the address held in _rs1_ + be naturally aligned to the size of the operand (i.e., eight-byte + aligned for _doublewords_ and four-byte aligned for _words_). If the + address is not naturally aligned, an address-misaligned exception or an + access-fault exception will be generated. The access-fault exception can + be generated for a memory access that would otherwise be able to + complete except for the misalignment, if the misaligned access should + not be emulated. + [NOTE] + ==== + Emulating misaligned LR/SC sequences is impractical in most systems. + + Misaligned LR/SC sequences also raise the possibility of accessing + multiple reservation sets at once, which present definitions do not + provide for. + ==== + + An implementation can register an arbitrarily large reservation set on + each LR, provided the reservation set includes all bytes of the + addressed data word or doubleword. An SC can only pair with the most + recent LR in program order. An SC may succeed only if no store from + another hart to the reservation set can be observed to have occurred + between the LR and the SC, and if there is no other SC between the LR + and itself in program order. An SC may succeed only if no write from a + device other than a hart to the bytes accessed by the LR instruction can + be observed to have occurred between the LR and SC. Note this LR might + have had a different effective address and data size, but reserved the + SC's address as part of the reservation set. + + [NOTE] + ==== + Following this model, in systems with memory translation, an SC is + allowed to succeed if the earlier LR reserved the same location using an + alias with a different virtual address, but is also allowed to fail if + the virtual address is different. + + To accommodate legacy devices and buses, writes from devices other than + RISC-V harts are only required to invalidate reservations when they + overlap the bytes accessed by the LR. These writes are not required to + invalidate the reservation when they access other bytes in the + reservation set. + ==== + + The SC must fail if the address is not within the reservation set of the + most recent LR in program order. The SC must fail if a store to the + reservation set from another hart can be observed to occur between the + LR and SC. The SC must fail if a write from some other device to the + bytes accessed by the LR can be observed to occur between the LR and SC. + (If such a device writes the reservation set but does not write the + bytes accessed by the LR, the SC may or may not fail.) An SC must fail + if there is another SC (to any address) between the LR and the SC in + program order. The precise statement of the atomicity requirements for + successful LR/SC sequences is defined by the Atomicity Axiom in + <>. + + [NOTE] + ==== + The platform should provide a means to determine the size and shape of + the reservation set. + + A platform specification may constrain the size and shape of the + reservation set. + + A store-conditional instruction to a scratch word of memory should be + used to forcibly invalidate any existing load reservation: + + * during a preemptive context switch, and + * if necessary when changing virtual to physical address mappings, such + as when migrating pages that might contain an active reservation. + + The invalidation of a hart's reservation when it executes an LR or SC + imply that a hart can only hold one reservation at a time, and that an + SC can only pair with the most recent LR, and LR with the next following + SC, in program order. This is a restriction to the Atomicity Axiom in + <> that ensures software runs correctly on + expected common implementations that operate in this manner. + ==== + + An SC instruction can never be observed by another RISC-V hart before + the LR instruction that established the reservation. + + [NOTE] + ==== + The LR/SC sequence + can be given acquire semantics by setting the _aq_ bit on the LR + instruction. The LR/SC sequence can be given release semantics by + by setting the _rl_ bit on the SC instruction. Assuming + suitable mappings for other atomic operations, setting the + _aq_ bit on the LR instruction, and setting the + _rl_ bit on the SC instruction makes the LR/SC + sequence sequentially consistent in the C\++ `memory_order_seq_cst` + sense. Such a sequence does not act as a fence for ordering ordinary + load and store instructions before and after the sequence. Specific + instruction mappings for other C++ atomic operations, + or stronger notions of "sequential consistency", may require both + bits to be set on either or both of the LR or SC instruction. + + If neither bit is set on either LR or SC, the LR/SC sequence can be + observed to occur before or after surrounding memory operations from the + same RISC-V hart. This can be appropriate when the LR/SC sequence is + used to implement a parallel reduction operation. + ==== + + Software should not set the _rl_ bit on an LR instruction unless the + _aq_ bit is also set, nor should software set the _aq_ bit on an SC + instruction unless the _rl_ bit is also set. LR._rl_ and SC._aq_ + instructions are not guaranteed to provide any stronger ordering than + those with both bits clear, but may result in lower performance. + + <<< + + [[cas]] + [source,asm] + .Sample code for compare-and-swap function using LR/SC. + # a0 holds address of memory location + # a1 holds expected value + # a2 holds desired value + # a0 holds return value, 0 if successful, !0 otherwise + cas: + lr.w t0, (a0) # Load original value. + bne t0, a1, fail # Doesn't match, so fail. + sc.w t0, a2, (a0) # Try to update. + bnez t0, cas # Retry if store-conditional failed. + li a0, 0 # Set return to success. + jr ra # Return. + fail: + li a0, 1 # Set return to failure. + jr ra # Return. + + LR/SC can be used to construct lock-free data structures. An example + using LR/SC to implement a compare-and-swap function is shown in + <>. If inlined, compare-and-swap functionality need only take four instructions. + + [[sec:lrscseq]] + === Eventual Success of Store-Conditional Instructions + + The `Zalrsc` extension defines _constrained LR/SC loops_, which have + the following properties: + + * The loop comprises only an LR/SC sequence and code to retry the + sequence in the case of failure, and must comprise at most 16 + instructions placed sequentially in memory. + * An LR/SC sequence begins with an LR instruction and ends with an SC + instruction. The dynamic code executed between the LR and SC + instructions can only contain instructions from the base ''I'' + instruction set, excluding loads, stores, backward jumps, taken backward + branches, JALR, FENCE, and SYSTEM instructions. If the ''C'' extension + is supported, then compressed forms of the aforementioned ''I'' + instructions are also permitted. + * The code to retry a failing LR/SC sequence can contain backwards jumps + and/or branches to repeat the LR/SC sequence, but otherwise has the same + constraint as the code between the LR and SC. + * The LR and SC addresses must lie within a memory region with the + _LR/SC eventuality_ property. The execution environment is responsible + for communicating which regions have this property. + * The SC must be to the same effective address and of the same data size + as the latest LR executed by the same hart. + + LR/SC sequences that do not lie within constrained LR/SC loops are + _unconstrained_. Unconstrained LR/SC sequences might succeed on some + attempts on some implementations, but might never succeed on other + implementations. + + [NOTE] + ==== + We restricted the length of LR/SC loops to fit within 64 contiguous + instruction bytes in the base ISA to avoid undue restrictions on + instruction cache and TLB size and associativity. Similarly, we + disallowed other loads and stores within the loops to avoid restrictions + on data-cache associativity in simple implementations that track the + reservation within a private cache. The restrictions on branches and + jumps limit the time that can be spent in the sequence. Floating-point + operations and integer multiply/divide were disallowed to simplify the + operating system's emulation of these instructions on implementations + lacking appropriate hardware support. + + Software is not forbidden from using unconstrained LR/SC sequences, but + portable software must detect the case that the sequence repeatedly + fails, then fall back to an alternate code sequence that does not rely + on an unconstrained LR/SC sequence. Implementations are permitted to + unconditionally fail any unconstrained LR/SC sequence. + ==== + + If a hart _H_ enters a constrained LR/SC loop, the execution environment + must guarantee that one of the following events eventually occurs: + + * _H_ or some other hart executes a successful SC to the reservation set + of the LR instruction in _H_'s constrained LR/SC loops. + * Some other hart executes an unconditional store or AMO instruction to + the reservation set of the LR instruction in _H_'s constrained LR/SC + loop, or some other device in the system writes to that reservation set. + * _H_ executes a branch or jump that exits the constrained LR/SC loop. + * _H_ traps. + + [NOTE] + ==== + Note that these definitions permit an implementation to fail an SC + instruction occasionally for any reason, provided the aforementioned + guarantee is not violated. + + As a consequence of the eventuality guarantee, if some harts in an + execution environment are executing constrained LR/SC loops, and no + other harts or devices in the execution environment execute an + unconditional store or AMO to that reservation set, then at least one + hart will eventually exit its constrained LR/SC loop. By contrast, if + other harts or devices continue to write to that reservation set, it is + not guaranteed that any hart will exit its LR/SC loop. + + Loads and load-reserved instructions do not by themselves impede the + progress of other harts' LR/SC sequences. We note this constraint + implies, among other things, that loads and load-reserved instructions + executed by other harts (possibly within the same core) cannot impede + LR/SC progress indefinitely. For example, cache evictions caused by + another hart sharing the cache cannot impede LR/SC progress + indefinitely. Typically, this implies reservations are tracked + independently of evictions from any shared cache. Similarly, cache + misses caused by speculative execution within a hart cannot impede LR/SC + progress indefinitely. + + These definitions admit the possibility that SC instructions may + spuriously fail for implementation reasons, provided progress is + eventually made. + + One advantage of CAS is that it guarantees that some hart eventually + makes progress, whereas an LR/SC atomic sequence could livelock + indefinitely on some systems. To avoid this concern, we added an + architectural guarantee of livelock freedom for certain LR/SC sequences. + + Earlier versions of this specification imposed a stronger + starvation-freedom guarantee. However, the weaker livelock-freedom + guarantee is sufficient to implement the C11 and C++11 languages, and is + substantially easier to provide in some microarchitectural styles. + ==== \ No newline at end of file diff --git a/arch/ext/Zba.yaml b/arch/ext/Zba.yaml index a508fc365..73b105806 100644 --- a/arch/ext/Zba.yaml +++ b/arch/ext/Zba.yaml @@ -1,61 +1,63 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zba: - long_name: Address generation instructions - description: | - The Zba instructions can be used to accelerate the generation of addresses that index into - arrays of basic types (halfword, word, doubleword) using both unsigned word-sized and - XLEN-sized indices: a shifted index is added to a base address. +$schema: "ext_schema.json#" +kind: extension +name: Zba +long_name: Address generation instructions +description: | + The Zba instructions can be used to accelerate the generation of addresses that index into + arrays of basic types (halfword, word, doubleword) using both unsigned word-sized and + XLEN-sized indices: a shifted index is added to a base address. - The shift and add instructions do a left shift of 1, 2, or 3 because these are commonly found - in real-world code and because they can be implemented with a minimal amount of additional - hardware beyond that of the simple adder. This avoids lengthening the critical path in - implementations. + The shift and add instructions do a left shift of 1, 2, or 3 because these are commonly found + in real-world code and because they can be implemented with a minimal amount of additional + hardware beyond that of the simple adder. This avoids lengthening the critical path in + implementations. - While the shift and add instructions are limited to a maximum left shift of 3, the `slli` - instruction (from the base ISA) can be used to perform similar shifts for indexing into arrays - of wider elements. The `slli.uw` -- added in this extension -- can be used when the index is to - be interpreted as an unsigned word. - type: unprivileged - company: - name: RISC-V International - url: https://riscv.org - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2021-06 - repositories: - - url: https://github.com/riscv/riscv-bitmanip - branch: main - contributors: - - name: Jacob Bachmeyer - - name: Allen Baum - - name: Ari Ben - - name: Alex Bradbury - - name: Steven Brager - - name: Rogier Brussee - - name: Michael Clark - - name: Ken Dockser - - name: Paul Donahue - - name: Dennis Ferguson - - name: Fabian Giesen - - name: John Hauser - - name: Robert Henry - - name: Bruce Holt - - name: Po-wei Huang - - name: Ben Marshall - - name: Rex McCrary - - name: Lee Moore - - name: Jiri Moravec - - name: Samuel Neves - - name: Markus Oberhumer - - name: Christopher Olson - - name: Nils Pipenbrinck - - name: Joseph Rahmeh - - name: Xue Saw - - name: Tommy Thorn - - name: Philipp Tomsich - - name: Avishai Tvila - - name: Andrew Waterman - - name: Thomas Wicki - - name: Claire Wolf + While the shift and add instructions are limited to a maximum left shift of 3, the `slli` + instruction (from the base ISA) can be used to perform similar shifts for indexing into arrays + of wider elements. The `slli.uw` -- added in this extension -- can be used when the index is to + be interpreted as an unsigned word. +type: unprivileged +company: + name: RISC-V International + url: https://riscv.org +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2021-06 + repositories: + - url: https://github.com/riscv/riscv-bitmanip + branch: main + contributors: + - name: Jacob Bachmeyer + - name: Allen Baum + - name: Ari Ben + - name: Alex Bradbury + - name: Steven Brager + - name: Rogier Brussee + - name: Michael Clark + - name: Ken Dockser + - name: Paul Donahue + - name: Dennis Ferguson + - name: Fabian Giesen + - name: John Hauser + - name: Robert Henry + - name: Bruce Holt + - name: Po-wei Huang + - name: Ben Marshall + - name: Rex McCrary + - name: Lee Moore + - name: Jiri Moravec + - name: Samuel Neves + - name: Markus Oberhumer + - name: Christopher Olson + - name: Nils Pipenbrinck + - name: Joseph Rahmeh + - name: Xue Saw + - name: Tommy Thorn + - name: Philipp Tomsich + - name: Avishai Tvila + - name: Andrew Waterman + - name: Thomas Wicki + - name: Claire Wolf diff --git a/arch/ext/Zbb.yaml b/arch/ext/Zbb.yaml index 15d6b7be4..747b4f74e 100644 --- a/arch/ext/Zbb.yaml +++ b/arch/ext/Zbb.yaml @@ -1,49 +1,51 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zbb: - long_name: Basic bit manipulation - description: | - Basic bit manipulation - type: unprivileged - company: - name: RISC-V International - url: https://riscv.org - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2021-06 - repositories: - - url: https://github.com/riscv/riscv-bitmanip - branch: main - contributors: - - name: Jacob Bachmeyer - - name: Allen Baum - - name: Ari Ben - - name: Alex Bradbury - - name: Steven Brager - - name: Rogier Brussee - - name: Michael Clark - - name: Ken Dockser - - name: Paul Donahue - - name: Dennis Ferguson - - name: Fabian Giesen - - name: John Hauser - - name: Robert Henry - - name: Bruce Holt - - name: Po-wei Huang - - name: Ben Marshall - - name: Rex McCrary - - name: Lee Moore - - name: Jiri Moravec - - name: Samuel Neves - - name: Markus Oberhumer - - name: Christopher Olson - - name: Nils Pipenbrinck - - name: Joseph Rahmeh - - name: Xue Saw - - name: Tommy Thorn - - name: Philipp Tomsich - - name: Avishai Tvila - - name: Andrew Waterman - - name: Thomas Wicki - - name: Claire Wolf +$schema: "ext_schema.json#" +kind: extension +name: Zbb +long_name: Basic bit manipulation +description: | + Basic bit manipulation +type: unprivileged +company: + name: RISC-V International + url: https://riscv.org +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2021-06 + repositories: + - url: https://github.com/riscv/riscv-bitmanip + branch: main + contributors: + - name: Jacob Bachmeyer + - name: Allen Baum + - name: Ari Ben + - name: Alex Bradbury + - name: Steven Brager + - name: Rogier Brussee + - name: Michael Clark + - name: Ken Dockser + - name: Paul Donahue + - name: Dennis Ferguson + - name: Fabian Giesen + - name: John Hauser + - name: Robert Henry + - name: Bruce Holt + - name: Po-wei Huang + - name: Ben Marshall + - name: Rex McCrary + - name: Lee Moore + - name: Jiri Moravec + - name: Samuel Neves + - name: Markus Oberhumer + - name: Christopher Olson + - name: Nils Pipenbrinck + - name: Joseph Rahmeh + - name: Xue Saw + - name: Tommy Thorn + - name: Philipp Tomsich + - name: Avishai Tvila + - name: Andrew Waterman + - name: Thomas Wicki + - name: Claire Wolf diff --git a/arch/ext/Zbc.yaml b/arch/ext/Zbc.yaml index dc8efb85c..671fb9c21 100644 --- a/arch/ext/Zbc.yaml +++ b/arch/ext/Zbc.yaml @@ -1,51 +1,53 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zbc: - long_name: Carry-less multiplication scalar instructions - description: | - Carry-less multiplication is the multiplication in the polynomial ring over GF(2). - type: unprivileged - company: - name: RISC-V International - url: https://riscv.org - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2021-06 - repositories: - - url: https://github.com/riscv/riscv-bitmanip - branch: main - contributors: - - name: Jacob Bachmeyer - - name: Allen Baum - - name: Ari Ben - - name: Alex Bradbury - - name: Steven Brager - - name: Rogier Brussee - - name: Michael Clark - - name: Ken Dockser - - name: Paul Donahue - - name: Dennis Ferguson - - name: Fabian Giesen - - name: John Hauser - - name: Robert Henry - - name: Bruce Holt - - name: Po-wei Huang - - name: Ben Marshall - - name: Rex McCrary - - name: Lee Moore - - name: Jiri Moravec - - name: Samuel Neves - - name: Markus Oberhumer - - name: Christopher Olson - - name: Nils Pipenbrinck - - name: Joseph Rahmeh - - name: Xue Saw - - name: Tommy Thorn - - name: Philipp Tomsich - - name: Avishai Tvila - - name: Andrew Waterman - - name: Thomas Wicki - - name: Claire Wolf +$schema: "ext_schema.json#" +kind: extension +name: Zbc +long_name: Carry-less multiplication scalar instructions +description: | + Carry-less multiplication is the multiplication in the polynomial ring over GF(2). +type: unprivileged +company: + name: RISC-V International + url: https://riscv.org +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2021-06 + repositories: + - url: https://github.com/riscv/riscv-bitmanip + branch: main + contributors: + - name: Jacob Bachmeyer + - name: Allen Baum + - name: Ari Ben + - name: Alex Bradbury + - name: Steven Brager + - name: Rogier Brussee + - name: Michael Clark + - name: Ken Dockser + - name: Paul Donahue + - name: Dennis Ferguson + - name: Fabian Giesen + - name: John Hauser + - name: Robert Henry + - name: Bruce Holt + - name: Po-wei Huang + - name: Ben Marshall + - name: Rex McCrary + - name: Lee Moore + - name: Jiri Moravec + - name: Samuel Neves + - name: Markus Oberhumer + - name: Christopher Olson + - name: Nils Pipenbrinck + - name: Joseph Rahmeh + - name: Xue Saw + - name: Tommy Thorn + - name: Philipp Tomsich + - name: Avishai Tvila + - name: Andrew Waterman + - name: Thomas Wicki + - name: Claire Wolf diff --git a/arch/ext/Zbs.yaml b/arch/ext/Zbs.yaml index 48a39c1ee..ac5e67835 100644 --- a/arch/ext/Zbs.yaml +++ b/arch/ext/Zbs.yaml @@ -1,56 +1,58 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zbs: - long_name: Single-bit instructions - description: | - The single-bit instructions provide a mechanism to set, clear, invert, or extract a single bit - in a register. The bit is specified by its index - type: unprivileged - company: - name: RISC-V International - url: https://riscv.org - doc_license: - name: Creative Commons Attribution 4.0 International License (CC-BY 4.0) - url: https://creativecommons.org/licenses/by/4.0/ - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2021-06 - url: https://drive.google.com/drive/u/0/folders/1_wqb-rXOVkGa6rqmugN3kwCftWDf1daU - repositories: - - url: https://github.com/riscv/riscv-bitmanip - branch: main - contributors: - - name: Jacob Bachmeyer - - name: Allen Baum - - name: Ari Ben - - name: Alex Bradbury - - name: Steven Brager - - name: Rogier Brussee - - name: Michael Clark - - name: Ken Dockser - - name: Paul Donahue - - name: Dennis Ferguson - - name: Fabian Giesen - - name: John Hauser - - name: Robert Henry - - name: Bruce Holt - - name: Po-wei Huang - - name: Ben Marshall - - name: Rex McCrary - - name: Lee Moore - - name: Jiri Moravec - - name: Samuel Neves - - name: Markus Oberhumer - - name: Christopher Olson - - name: Nils Pipenbrinck - - name: Joseph Rahmeh - - name: Xue Saw - - name: Tommy Thorn - - name: Philipp Tomsich - - name: Avishai Tvila - - name: Andrew Waterman - - name: Thomas Wicki - - name: Claire Wolf +$schema: "ext_schema.json#" +kind: extension +name: Zbs +long_name: Single-bit instructions +description: | + The single-bit instructions provide a mechanism to set, clear, invert, or extract a single bit + in a register. The bit is specified by its index +type: unprivileged +company: + name: RISC-V International + url: https://riscv.org +doc_license: + name: Creative Commons Attribution 4.0 International License (CC-BY 4.0) + url: https://creativecommons.org/licenses/by/4.0/ +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2021-06 + url: https://drive.google.com/drive/u/0/folders/1_wqb-rXOVkGa6rqmugN3kwCftWDf1daU + repositories: + - url: https://github.com/riscv/riscv-bitmanip + branch: main + contributors: + - name: Jacob Bachmeyer + - name: Allen Baum + - name: Ari Ben + - name: Alex Bradbury + - name: Steven Brager + - name: Rogier Brussee + - name: Michael Clark + - name: Ken Dockser + - name: Paul Donahue + - name: Dennis Ferguson + - name: Fabian Giesen + - name: John Hauser + - name: Robert Henry + - name: Bruce Holt + - name: Po-wei Huang + - name: Ben Marshall + - name: Rex McCrary + - name: Lee Moore + - name: Jiri Moravec + - name: Samuel Neves + - name: Markus Oberhumer + - name: Christopher Olson + - name: Nils Pipenbrinck + - name: Joseph Rahmeh + - name: Xue Saw + - name: Tommy Thorn + - name: Philipp Tomsich + - name: Avishai Tvila + - name: Andrew Waterman + - name: Thomas Wicki + - name: Claire Wolf diff --git a/arch/ext/Zfhmin.yaml b/arch/ext/Zfhmin.yaml index 1ec9dd0c8..2f68bfb7a 100644 --- a/arch/ext/Zfhmin.yaml +++ b/arch/ext/Zfhmin.yaml @@ -1,51 +1,53 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zfhmin: - long_name: Minimal half-precision Floating-point - description: | - `Zfhmin` provides - minimal support for 16-bit half-precision binary floating-point - instructions. The Zfhmin extension is a subset of the `Zfh` extension, - consisting only of data transfer and conversion instructions. Like `Zfh`, - the `Zfhmin` extension depends on the single-precision floating-point - extension, `F`. The expectation is that `Zfhmin` software primarily uses the - half-precision format for storage, performing most computation in higher - precision. +$schema: "ext_schema.json#" +kind: extension +name: Zfhmin +long_name: Minimal half-precision Floating-point +description: | + `Zfhmin` provides + minimal support for 16-bit half-precision binary floating-point + instructions. The Zfhmin extension is a subset of the `Zfh` extension, + consisting only of data transfer and conversion instructions. Like `Zfh`, + the `Zfhmin` extension depends on the single-precision floating-point + extension, `F`. The expectation is that `Zfhmin` software primarily uses the + half-precision format for storage, performing most computation in higher + precision. - The `Zfhmin` extension includes the following instructions from the `Zfh` - extension: `flh`, `fsh`, `fmv.x.h`, `fmv.h.x`, `fcvt.s.h`, and `fcvt.h.s`. - If the `D` extension is present, the `fcvt.d.h` and `fcvt.h.d` instructions are also - included. If the `Q` extension is present, the `fcvt.q.h` and `fcvt.h.q` - instructions are additionally included. + The `Zfhmin` extension includes the following instructions from the `Zfh` + extension: `flh`, `fsh`, `fmv.x.h`, `fmv.h.x`, `fcvt.s.h`, and `fcvt.h.s`. + If the `D` extension is present, the `fcvt.d.h` and `fcvt.h.d` instructions are also + included. If the `Q` extension is present, the `fcvt.q.h` and `fcvt.h.q` + instructions are additionally included. - [NOTE] - ==== - `Zfhmin` does not include the `fsgnj.h` instruction, because it suffices to - instead use the `fsgnj.s` instruction to move half-precision values - between floating-point registers. + [NOTE] + ==== + `Zfhmin` does not include the `fsgnj.h` instruction, because it suffices to + instead use the `fsgnj.s` instruction to move half-precision values + between floating-point registers. - Half-precision addition, subtraction, multiplication, division, and - square-root operations can be faithfully emulated by converting the - half-precision operands to single-precision, performing the operation - using single-precision arithmetic, then converting back to - half-precision. cite:[roux:hal-01091186] Performing half-precision fused multiply-addition using - this method incurs a 1-ulp error on some inputs for the RNE and RMM - rounding modes. + Half-precision addition, subtraction, multiplication, division, and + square-root operations can be faithfully emulated by converting the + half-precision operands to single-precision, performing the operation + using single-precision arithmetic, then converting back to + half-precision. cite:[roux:hal-01091186] Performing half-precision fused multiply-addition using + this method incurs a 1-ulp error on some inputs for the RNE and RMM + rounding modes. - Conversion from 8- or 16-bit integers to half-precision can be emulated - by first converting to single-precision, then converting to - half-precision. Conversion from 32-bit integer can be emulated by first - converting to double-precision. If the `D` extension is not present and a - 1-ulp error under RNE or RMM is tolerable, 32-bit integers can be first - converted to single-precision instead. The same remark applies to - conversions from 64-bit integers without the `Q` extension. - ==== - type: unprivileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2021-11 - requires: - name: F - version: ">= 2.2" + Conversion from 8- or 16-bit integers to half-precision can be emulated + by first converting to single-precision, then converting to + half-precision. Conversion from 32-bit integer can be emulated by first + converting to double-precision. If the `D` extension is not present and a + 1-ulp error under RNE or RMM is tolerable, 32-bit integers can be first + converted to single-precision instead. The same remark applies to + conversions from 64-bit integers without the `Q` extension. + ==== +type: unprivileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2021-11 + requires: + name: F + version: ">= 2.2" diff --git a/arch/ext/Zic64b.yaml b/arch/ext/Zic64b.yaml index 40cf2a5eb..15395d5ec 100644 --- a/arch/ext/Zic64b.yaml +++ b/arch/ext/Zic64b.yaml @@ -1,30 +1,32 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zic64b: - long_name: 64-byte cache blocks - description: | - Cache blocks must be 64 bytes in size, naturally aligned in the address space. +$schema: "ext_schema.json#" +kind: extension +name: Zic64b +long_name: 64-byte cache blocks +description: | + Cache blocks must be 64 bytes in size, naturally aligned in the address space. - [NOTE] - This extension was ratified with the RVA20 profiles. - type: privileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: null - url: https://github.com/riscv/riscv-profiles/releases/tag/v1.0 - repositories: - - url: https://github.com/riscv/riscv-profiles - branch: main - contributors: - - name: Krste Asanovic - company: SiFive, Inc. - requires: - anyOf: - - name: Zicbom - - name: Zicboz - - name: Zicbop - param_constraints: - CACHE_BLOCK_SIZE: - schema: - const: 64 + [NOTE] + This extension was ratified with the RVA20 profiles. +type: privileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: null + url: https://github.com/riscv/riscv-profiles/releases/tag/v1.0 + repositories: + - url: https://github.com/riscv/riscv-profiles + branch: main + contributors: + - name: Krste Asanovic + company: SiFive, Inc. + requires: + anyOf: + - name: Zicbom + - name: Zicboz + - name: Zicbop + param_constraints: + CACHE_BLOCK_SIZE: + schema: + const: 64 diff --git a/arch/ext/Zicbom.yaml b/arch/ext/Zicbom.yaml index 8bdaa67eb..23206267c 100644 --- a/arch/ext/Zicbom.yaml +++ b/arch/ext/Zicbom.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zicbom: - long_name: Cache block management instructions - description: Cache block management instructions - type: unprivileged - versions: - - version: "1.0.1-b34ea8a" - state: ratified - ratification_date: 2022-05 - params: - CACHE_BLOCK_SIZE: - description: | - The observable size of a cache block, in bytes - also_defined_in: [Zicboz, Zicbop] - schema: - type: integer - FORCE_UPGRADE_CBO_INVAL_TO_FLUSH: - description: | - When true, an implementation prohibits setting `menvcfg.CBIE` == `11` such that all `cbo.inval` - instructions either trap (when `menvcfg.CBIE` == '00') or flush (when `menvcfg.CBIE` == '01'). +$schema: "ext_schema.json#" +kind: extension +name: Zicbom +long_name: Cache block management instructions +description: Cache block management instructions +type: unprivileged +versions: +- version: "1.0.1-b34ea8a" + state: ratified + ratification_date: 2022-05 +params: + CACHE_BLOCK_SIZE: + description: | + The observable size of a cache block, in bytes + also_defined_in: [Zicboz, Zicbop] + schema: + type: integer + FORCE_UPGRADE_CBO_INVAL_TO_FLUSH: + description: | + When true, an implementation prohibits setting `menvcfg.CBIE` == `11` such that all `cbo.inval` + instructions either trap (when `menvcfg.CBIE` == '00') or flush (when `menvcfg.CBIE` == '01'). - When false, an implementation allows a true INVAL operation for `cbo.inval`, and thus supports - the setting `menvcfg.CBIE` == `11`. - schema: - type: boolean + When false, an implementation allows a true INVAL operation for `cbo.inval`, and thus supports + the setting `menvcfg.CBIE` == `11`. + schema: + type: boolean diff --git a/arch/ext/Zicbop.yaml b/arch/ext/Zicbop.yaml index a4f2d7dc7..3cd9c3d01 100644 --- a/arch/ext/Zicbop.yaml +++ b/arch/ext/Zicbop.yaml @@ -1,17 +1,19 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zicbop: - long_name: Cache block prefetch - description: Cache block prefetch instruction - type: unprivileged - versions: - - version: 1.0.1-b34ea8a - state: ratified - ratification_date: 2022-05 - params: - CACHE_BLOCK_SIZE: - description: | - The observable size of a cache block, in bytes - also_defined_in: [Zicboz, Zicbom] - schema: - type: integer +$schema: "ext_schema.json#" +kind: extension +name: Zicbop +long_name: Cache block prefetch +description: Cache block prefetch instruction +type: unprivileged +versions: +- version: 1.0.1-b34ea8a + state: ratified + ratification_date: 2022-05 +params: + CACHE_BLOCK_SIZE: + description: | + The observable size of a cache block, in bytes + also_defined_in: [Zicboz, Zicbom] + schema: + type: integer diff --git a/arch/ext/Zicboz.yaml b/arch/ext/Zicboz.yaml index ce47b8860..84bd7cf42 100644 --- a/arch/ext/Zicboz.yaml +++ b/arch/ext/Zicboz.yaml @@ -1,17 +1,19 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zicboz: - long_name: Cache block zero instruction - description: Cache block zero instruction - type: unprivileged - versions: - - version: 1.0.1-b34ea8a - state: ratified - ratification_date: 2022-05 - params: - CACHE_BLOCK_SIZE: - description: | - The observable size of a cache block, in bytes - also_defined_in: [Zicbom, Zicbop] - schema: - type: integer \ No newline at end of file +$schema: "ext_schema.json#" +kind: extension +name: Zicboz +long_name: Cache block zero instruction +description: Cache block zero instruction +type: unprivileged +versions: +- version: 1.0.1-b34ea8a + state: ratified + ratification_date: 2022-05 +params: + CACHE_BLOCK_SIZE: + description: | + The observable size of a cache block, in bytes + also_defined_in: [Zicbom, Zicbop] + schema: + type: integer \ No newline at end of file diff --git a/arch/ext/Ziccamoa.yaml b/arch/ext/Ziccamoa.yaml index 0a5a334ff..838438db1 100644 --- a/arch/ext/Ziccamoa.yaml +++ b/arch/ext/Ziccamoa.yaml @@ -1,14 +1,15 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Ziccamoa: - name: Main memory atmoicity - long_name: Main memory atomicity requirement for RVA profiles - description: | - Main memory regions with both the cacheability and coherence PMAs must support AMOArithmetic. +$schema: "ext_schema.json#" +kind: extension +name: Ziccamoa +long_name: Main memory atomicity requirement for RVA profiles +description: | + Main memory regions with both the cacheability and coherence PMAs must support AMOArithmetic. - [NOTE] - This extension was ratified as part of the RVA20 profile. - versions: - - version: "1.0.0" - state: ratified - ratification_date: null + [NOTE] + This extension was ratified as part of the RVA20 profile. +versions: +- version: "1.0.0" + state: ratified + ratification_date: null diff --git a/arch/ext/Ziccif.yaml b/arch/ext/Ziccif.yaml index 19695af57..4a35d7b00 100644 --- a/arch/ext/Ziccif.yaml +++ b/arch/ext/Ziccif.yaml @@ -1,16 +1,17 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Ziccif: - name: Main memory fetch - long_name: Main memory fetch requirement for RVA profiles - description: | - Main memory regions with both the cacheability and coherence PMAs must support instruction - fetch, and any instruction fetches of naturally aligned power-of-2 sizes up to - min(ILEN,XLEN) (i.e., 32 bits for RVA22) are atomic. +$schema: "ext_schema.json#" +kind: extension +name: Ziccif +long_name: Main memory fetch requirement for RVA profiles +description: | + Main memory regions with both the cacheability and coherence PMAs must support instruction + fetch, and any instruction fetches of naturally aligned power-of-2 sizes up to + min(ILEN,XLEN) (i.e., 32 bits for RVA22) are atomic. - [NOTE] - This extension was ratified as part of the RVA20 profile. - versions: - - version: "1.0.0" - state: ratified - ratification_date: null + [NOTE] + This extension was ratified as part of the RVA20 profile. +versions: +- version: "1.0.0" + state: ratified + ratification_date: null diff --git a/arch/ext/Zicclsm.yaml b/arch/ext/Zicclsm.yaml index f8aed3820..835e91223 100644 --- a/arch/ext/Zicclsm.yaml +++ b/arch/ext/Zicclsm.yaml @@ -1,26 +1,27 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zicclsm: - name: Misaligned load/store support in main memory. - long_name: Main memory misaligned requirement for RVA profiles - description: | - Misaligned loads and stores to main memory regions with both the cacheability and coherence - PMAs must be supported. +$schema: "ext_schema.json#" +kind: extension +name: Zicclsm +long_name: Main memory misaligned requirement for RVA profiles +description: | + Misaligned loads and stores to main memory regions with both the cacheability and coherence + PMAs must be supported. - [NOTE] - This extension was ratified as part of the RVA20 profile. + [NOTE] + This extension was ratified as part of the RVA20 profile. - [NOTE] - This requires misaligned support for all regular load and store instructions (including - scalar and vector) but not AMOs or other specialized forms of memory access. - Even though mandated, misaligned loads and stores might execute extremely slowly. - Standard software distributions should assume their existence only for correctness, - not for performance. - versions: - - version: "1.0.0" - state: ratified - ratification_date: null - param_constraints: - MISALIGNED_LDST: - schema: - const: true + [NOTE] + This requires misaligned support for all regular load and store instructions (including + scalar and vector) but not AMOs or other specialized forms of memory access. + Even though mandated, misaligned loads and stores might execute extremely slowly. + Standard software distributions should assume their existence only for correctness, + not for performance. +versions: +- version: "1.0.0" + state: ratified + ratification_date: null + param_constraints: + MISALIGNED_LDST: + schema: + const: true diff --git a/arch/ext/Ziccrse.yaml b/arch/ext/Ziccrse.yaml index ba787a743..93e7539b8 100644 --- a/arch/ext/Ziccrse.yaml +++ b/arch/ext/Ziccrse.yaml @@ -1,14 +1,15 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Ziccrse: - name: Main memory reservability - long_name: Main memory reservability requirement for RVA profiles - description: | - Main memory regions with both the cacheability and coherence PMAs must support RsrvEventual. +$schema: "ext_schema.json#" +kind: extension +name: Ziccrse +long_name: Main memory reservability requirement for RVA profiles +description: | + Main memory regions with both the cacheability and coherence PMAs must support RsrvEventual. - [NOTE] - This extension was ratified as part of the RVA20 profile. - versions: - - version: "1.0.0" - state: ratified - ratification_date: null + [NOTE] + This extension was ratified as part of the RVA20 profile. +versions: +- version: "1.0.0" + state: ratified + ratification_date: null diff --git a/arch/ext/Zicfilp.yaml b/arch/ext/Zicfilp.yaml index 8afd832d0..27613044c 100644 --- a/arch/ext/Zicfilp.yaml +++ b/arch/ext/Zicfilp.yaml @@ -1,31 +1,33 @@ -Zicfilp: - long_name: Landing Pads - description: | - TODO - type: unprivileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2024-07 - params: - REPORT_CAUSE_IN_MTVAL_ON_LANDING_PAD_SOFTWARE_CHECK: - description: | - When true, `mtval` is written with the shadow stack casue (code=18) when a SoftwareCheck exception is raised into M-mode due to a landing pad error. +$schema: "ext_schema.json#" +kind: extension +name: Zicfilp +long_name: Landing Pads +description: | + TODO +type: unprivileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2024-07 +params: + REPORT_CAUSE_IN_MTVAL_ON_LANDING_PAD_SOFTWARE_CHECK: + description: | + When true, `mtval` is written with the shadow stack casue (code=18) when a SoftwareCheck exception is raised into M-mode due to a landing pad error. - When false, `mtval` is written with 0. - schema: - type: boolean - REPORT_CAUSE_IN_STVAL_ON_LANDING_PAD_SOFTWARE_CHECK: - description: | - When true, `stval` is written with the shadow stack casue (code=18) when a SoftwareCheck exception is raised into S-mode due to a landing pad error. + When false, `mtval` is written with 0. + schema: + type: boolean + REPORT_CAUSE_IN_STVAL_ON_LANDING_PAD_SOFTWARE_CHECK: + description: | + When true, `stval` is written with the shadow stack casue (code=18) when a SoftwareCheck exception is raised into S-mode due to a landing pad error. - When false, `stval` is written with 0. - schema: - type: boolean - REPORT_CAUSE_IN_VSTVAL_ON_LANDING_PAD_SOFTWARE_CHECK: - description: | - When true, `vstval` is written with the shadow stack casue (code=18) when a SoftwareCheck exception is raised into VS-mode due to a landing pad error. + When false, `stval` is written with 0. + schema: + type: boolean + REPORT_CAUSE_IN_VSTVAL_ON_LANDING_PAD_SOFTWARE_CHECK: + description: | + When true, `vstval` is written with the shadow stack casue (code=18) when a SoftwareCheck exception is raised into VS-mode due to a landing pad error. - When false, `vstval` is written with 0. - schema: - type: boolean + When false, `vstval` is written with 0. + schema: + type: boolean diff --git a/arch/ext/Zicfiss.yaml b/arch/ext/Zicfiss.yaml index b9104cfcd..41c0b0e6c 100644 --- a/arch/ext/Zicfiss.yaml +++ b/arch/ext/Zicfiss.yaml @@ -1,33 +1,35 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zicfiss: - long_name: Shadow Stack - description: | - TODO - type: unprivileged - versions: - - version: "1.0.0" - state: ratified - ratification_date: 2024-07 - params: - REPORT_CAUSE_IN_MTVAL_ON_SHADOW_STACK_SOFTWARE_CHECK: - description: | - When true, `mtval` is written with the shadow stack casue (code=3) when a SoftwareCheck exception is raised into M-mode due to a shadow stack pop check instruction. +$schema: "ext_schema.json#" +kind: extension +name: Zicfiss +long_name: Shadow Stack +description: | + TODO +type: unprivileged +versions: +- version: "1.0.0" + state: ratified + ratification_date: 2024-07 +params: + REPORT_CAUSE_IN_MTVAL_ON_SHADOW_STACK_SOFTWARE_CHECK: + description: | + When true, `mtval` is written with the shadow stack casue (code=3) when a SoftwareCheck exception is raised into M-mode due to a shadow stack pop check instruction. - When false, `mtval` is written with 0. - schema: - type: boolean - REPORT_CAUSE_IN_STVAL_ON_SHADOW_STACK_SOFTWARE_CHECK: - description: | - When true, `stval` is written with the shadow stack casue (code=3) when a SoftwareCheck exception is raised into S-mode due to a shadow stack pop check instruction. + When false, `mtval` is written with 0. + schema: + type: boolean + REPORT_CAUSE_IN_STVAL_ON_SHADOW_STACK_SOFTWARE_CHECK: + description: | + When true, `stval` is written with the shadow stack casue (code=3) when a SoftwareCheck exception is raised into S-mode due to a shadow stack pop check instruction. - When false, `stval` is written with 0. - schema: - type: boolean - REPORT_CAUSE_IN_VSTVAL_ON_SHADOW_STACK_SOFTWARE_CHECK: - description: | - When true, `vstval` is written with the shadow stack casue (code=3) when a SoftwareCheck exception is raised into VS-mode due to a shadow stack pop check instruction. + When false, `stval` is written with 0. + schema: + type: boolean + REPORT_CAUSE_IN_VSTVAL_ON_SHADOW_STACK_SOFTWARE_CHECK: + description: | + When true, `vstval` is written with the shadow stack casue (code=3) when a SoftwareCheck exception is raised into VS-mode due to a shadow stack pop check instruction. - When false, `vstval` is written with 0. - schema: - type: boolean + When false, `vstval` is written with 0. + schema: + type: boolean diff --git a/arch/ext/Zicntr.yaml b/arch/ext/Zicntr.yaml index 3abf56fc9..bd791827a 100644 --- a/arch/ext/Zicntr.yaml +++ b/arch/ext/Zicntr.yaml @@ -1,31 +1,33 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zicntr: - long_name: Architectural performance counters - description: Architectural performance counters - type: unprivileged - versions: - - version: "2.0.0" - state: ratified - ratification_date: 2019-12 - requires: - name: Zicsr - version: ">= 2.0" - params: - TIME_CSR_IMPLEMENTED: - description: | - Whether or not a real hardware `time` CSR exists. Implementations can either provide a real - CSR or emulate access at M-mode. +$schema: "ext_schema.json#" +kind: extension +name: Zicntr +long_name: Architectural performance counters +description: Architectural performance counters +type: unprivileged +versions: +- version: "2.0.0" + state: ratified + ratification_date: 2019-12 + requires: + name: Zicsr + version: ">= 2.0" +params: + TIME_CSR_IMPLEMENTED: + description: | + Whether or not a real hardware `time` CSR exists. Implementations can either provide a real + CSR or emulate access at M-mode. - Possible values: + Possible values: - true:: - `time`/`timeh` exists, and accessing it will not cause an IllegalInstruction trap - - false:: - `time`/`timeh` does not exist. - Accessing the CSR will cause an IllegalInstruction trap or enter an unpredictable state, - depending on TRAP_ON_UNIMPLEMENTED_CSR. - Privileged software may emulate the `time` CSR, or may pass the exception to a lower level. - schema: - type: boolean \ No newline at end of file + true:: + `time`/`timeh` exists, and accessing it will not cause an IllegalInstruction trap + + false:: + `time`/`timeh` does not exist. + Accessing the CSR will cause an IllegalInstruction trap or enter an unpredictable state, + depending on TRAP_ON_UNIMPLEMENTED_CSR. + Privileged software may emulate the `time` CSR, or may pass the exception to a lower level. + schema: + type: boolean \ No newline at end of file diff --git a/arch/ext/Zicsr.yaml b/arch/ext/Zicsr.yaml index b5f77717f..92689331a 100644 --- a/arch/ext/Zicsr.yaml +++ b/arch/ext/Zicsr.yaml @@ -1,10 +1,12 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zicsr: - long_name: Control and status registers - description: Control and status registers - type: unprivileged - versions: - - version: "2.0.0" - state: ratified - ratification_date: null +$schema: "ext_schema.json#" +kind: extension +name: Zicsr +long_name: Control and status registers +description: Control and status registers +type: unprivileged +versions: +- version: "2.0.0" + state: ratified + ratification_date: null diff --git a/arch/ext/Zifencei.yaml b/arch/ext/Zifencei.yaml index 0c8616edf..7b661769b 100644 --- a/arch/ext/Zifencei.yaml +++ b/arch/ext/Zifencei.yaml @@ -1,70 +1,72 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zifencei: - long_name: Instruction fence - description: | - This chapter defines the "Zifencei" extension, which includes the - FENCE.I instruction that provides explicit synchronization between - writes to instruction memory and instruction fetches on the same hart. - Currently, this instruction is the only standard mechanism to ensure - that stores visible to a hart will also be visible to its instruction - fetches. - (((store instruction word, not included))) +$schema: "ext_schema.json#" +kind: extension +name: Zifencei +long_name: Instruction fence +description: | + This chapter defines the "Zifencei" extension, which includes the + FENCE.I instruction that provides explicit synchronization between + writes to instruction memory and instruction fetches on the same hart. + Currently, this instruction is the only standard mechanism to ensure + that stores visible to a hart will also be visible to its instruction + fetches. + (((store instruction word, not included))) - [NOTE] - ==== - We considered but did not include a "store instruction word" - instruction as in cite:[majc]. JIT compilers may generate a large trace of - instructions before a single FENCE.I, and amortize any instruction cache - snooping/invalidation overhead by writing translated instructions to - memory regions that are known not to reside in the I-cache. - ==== - ''' - [NOTE] - ==== - The FENCE.I instruction was designed to support a wide variety of - implementations. A simple implementation can flush the local instruction - cache and the instruction pipeline when the FENCE.I is executed. A more - complex implementation might snoop the instruction (data) cache on every - data (instruction) cache miss, or use an inclusive unified private L2 - cache to invalidate lines from the primary instruction cache when they - are being written by a local store instruction. If instruction and data - caches are kept coherent in this way, or if the memory system consists - of only uncached RAMs, then just the fetch pipeline needs to be flushed - at a FENCE.I. + [NOTE] + ==== + We considered but did not include a "store instruction word" + instruction as in cite:[majc]. JIT compilers may generate a large trace of + instructions before a single FENCE.I, and amortize any instruction cache + snooping/invalidation overhead by writing translated instructions to + memory regions that are known not to reside in the I-cache. + ==== + ''' + [NOTE] + ==== + The FENCE.I instruction was designed to support a wide variety of + implementations. A simple implementation can flush the local instruction + cache and the instruction pipeline when the FENCE.I is executed. A more + complex implementation might snoop the instruction (data) cache on every + data (instruction) cache miss, or use an inclusive unified private L2 + cache to invalidate lines from the primary instruction cache when they + are being written by a local store instruction. If instruction and data + caches are kept coherent in this way, or if the memory system consists + of only uncached RAMs, then just the fetch pipeline needs to be flushed + at a FENCE.I. - The FENCE.I instruction was previously part of the base I instruction - set. Two main issues are driving moving this out of the mandatory base, - although at time of writing it is still the only standard method for - maintaining instruction-fetch coherence. + The FENCE.I instruction was previously part of the base I instruction + set. Two main issues are driving moving this out of the mandatory base, + although at time of writing it is still the only standard method for + maintaining instruction-fetch coherence. - First, it has been recognized that on some systems, FENCE.I will be - expensive to implement and alternate mechanisms are being discussed in - the memory model task group. In particular, for designs that have an - incoherent instruction cache and an incoherent data cache, or where the - instruction cache refill does not snoop a coherent data cache, both - caches must be completely flushed when a FENCE.I instruction is - encountered. This problem is exacerbated when there are multiple levels - of I and D cache in front of a unified cache or outer memory system. + First, it has been recognized that on some systems, FENCE.I will be + expensive to implement and alternate mechanisms are being discussed in + the memory model task group. In particular, for designs that have an + incoherent instruction cache and an incoherent data cache, or where the + instruction cache refill does not snoop a coherent data cache, both + caches must be completely flushed when a FENCE.I instruction is + encountered. This problem is exacerbated when there are multiple levels + of I and D cache in front of a unified cache or outer memory system. - Second, the instruction is not powerful enough to make available at user - level in a Unix-like operating system environment. The FENCE.I only - synchronizes the local hart, and the OS can reschedule the user hart to - a different physical hart after the FENCE.I. This would require the OS - to execute an additional FENCE.I as part of every context migration. For - this reason, the standard Linux ABI has removed FENCE.I from user-level - and now requires a system call to maintain instruction-fetch coherence, - which allows the OS to minimize the number of FENCE.I executions - required on current systems and provides forward-compatibility with - future improved instruction-fetch coherence mechanisms. + Second, the instruction is not powerful enough to make available at user + level in a Unix-like operating system environment. The FENCE.I only + synchronizes the local hart, and the OS can reschedule the user hart to + a different physical hart after the FENCE.I. This would require the OS + to execute an additional FENCE.I as part of every context migration. For + this reason, the standard Linux ABI has removed FENCE.I from user-level + and now requires a system call to maintain instruction-fetch coherence, + which allows the OS to minimize the number of FENCE.I executions + required on current systems and provides forward-compatibility with + future improved instruction-fetch coherence mechanisms. - Future approaches to instruction-fetch coherence under discussion - include providing more restricted versions of FENCE.I that only target a - given address specified in _rs1_, and/or allowing software to use an ABI - that relies on machine-mode cache-maintenance operations. - ==== - type: unprivileged - versions: - - version: "2.0.0" - state: ratified - ratification_date: null + Future approaches to instruction-fetch coherence under discussion + include providing more restricted versions of FENCE.I that only target a + given address specified in _rs1_, and/or allowing software to use an ABI + that relies on machine-mode cache-maintenance operations. + ==== +type: unprivileged +versions: +- version: "2.0.0" + state: ratified + ratification_date: null diff --git a/arch/ext/Zihintpause.yaml b/arch/ext/Zihintpause.yaml index a4a8f10ef..06db29627 100644 --- a/arch/ext/Zihintpause.yaml +++ b/arch/ext/Zihintpause.yaml @@ -1,71 +1,73 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zihintpause: - long_name: PAUSE instruction - description: | - The PAUSE instruction is a HINT that indicates the current hart's rate - of instruction retirement should be temporarily reduced or paused. The - duration of its effect must be bounded and may be zero. - (((PAUSE, HINT))) - (((HINT, PAUSE))) +$schema: "ext_schema.json#" +kind: extension +name: Zihintpause +long_name: PAUSE instruction +description: | + The PAUSE instruction is a HINT that indicates the current hart's rate + of instruction retirement should be temporarily reduced or paused. The + duration of its effect must be bounded and may be zero. + (((PAUSE, HINT))) + (((HINT, PAUSE))) - [NOTE] - ==== - Software can use the PAUSE instruction to reduce energy consumption - while executing spin-wait code sequences. Multithreaded cores might - temporarily relinquish execution resources to other harts when PAUSE is - executed. It is recommended that a PAUSE instruction generally be - included in the code sequence for a spin-wait loop. - (((PAUSE, energy consumption))) + [NOTE] + ==== + Software can use the PAUSE instruction to reduce energy consumption + while executing spin-wait code sequences. Multithreaded cores might + temporarily relinquish execution resources to other harts when PAUSE is + executed. It is recommended that a PAUSE instruction generally be + included in the code sequence for a spin-wait loop. + (((PAUSE, energy consumption))) - A future extension might add primitives similar to the x86 MONITOR/MWAIT - instructions, which provide a more efficient mechanism to wait on writes - to a specific memory location. However, these instructions would not - supplant PAUSE. PAUSE is more appropriate when polling for non-memory - events, when polling for multiple events, or when software does not know - precisely what events it is polling for. + A future extension might add primitives similar to the x86 MONITOR/MWAIT + instructions, which provide a more efficient mechanism to wait on writes + to a specific memory location. However, these instructions would not + supplant PAUSE. PAUSE is more appropriate when polling for non-memory + events, when polling for multiple events, or when software does not know + precisely what events it is polling for. - The duration of a PAUSE instruction's effect may vary significantly - within and among implementations. In typical implementations this - duration should be much less than the time to perform a context switch, - probably more on the rough order of an on-chip cache miss latency or a - cacheless access to main memory. - (((PAUSE, duration))) + The duration of a PAUSE instruction's effect may vary significantly + within and among implementations. In typical implementations this + duration should be much less than the time to perform a context switch, + probably more on the rough order of an on-chip cache miss latency or a + cacheless access to main memory. + (((PAUSE, duration))) - A series of PAUSE instructions can be used to create a cumulative delay - loosely proportional to the number of PAUSE instructions. In spin-wait - loops in portable code, however, only one PAUSE instruction should be - used before re-evaluating loop conditions, else the hart might stall - longer than optimal on some implementations, degrading system - performance. - ==== + A series of PAUSE instructions can be used to create a cumulative delay + loosely proportional to the number of PAUSE instructions. In spin-wait + loops in portable code, however, only one PAUSE instruction should be + used before re-evaluating loop conditions, else the hart might stall + longer than optimal on some implementations, degrading system + performance. + ==== - PAUSE is encoded as a FENCE instruction with _pred_=`W`, _succ_=`0`, _fm_=`0`, - _rd_=`x0`, and _rs1_=`x0`. + PAUSE is encoded as a FENCE instruction with _pred_=`W`, _succ_=`0`, _fm_=`0`, + _rd_=`x0`, and _rs1_=`x0`. - //include::images/wavedrom/zihintpause-hint.edn[] - //[zihintpause-hint] - //.Zihintpause fence instructions + //include::images/wavedrom/zihintpause-hint.edn[] + //[zihintpause-hint] + //.Zihintpause fence instructions - [NOTE] - ==== - PAUSE is encoded as a hint within the FENCE opcode because some - implementations are expected to deliberately stall the PAUSE instruction - until outstanding memory transactions have completed. Because the - successor set is null, however, PAUSE does not _mandate_ any particular - memory ordering--hence, it truly is a HINT. - (((PAUSE, encoding))) + [NOTE] + ==== + PAUSE is encoded as a hint within the FENCE opcode because some + implementations are expected to deliberately stall the PAUSE instruction + until outstanding memory transactions have completed. Because the + successor set is null, however, PAUSE does not _mandate_ any particular + memory ordering--hence, it truly is a HINT. + (((PAUSE, encoding))) - Like other FENCE instructions, PAUSE cannot be used within LR/SC - sequences without voiding the forward-progress guarantee. - (((PAUSE, LR/RC sequences))) + Like other FENCE instructions, PAUSE cannot be used within LR/SC + sequences without voiding the forward-progress guarantee. + (((PAUSE, LR/RC sequences))) - The choice of a predecessor set of W is arbitrary, since the successor - set is null. Other HINTs similar to PAUSE might be encoded with other - predecessor sets. - ==== - type: unprivileged - versions: - - version: "2.0.0" - state: ratified - ratification_date: null + The choice of a predecessor set of W is arbitrary, since the successor + set is null. Other HINTs similar to PAUSE might be encoded with other + predecessor sets. + ==== +type: unprivileged +versions: +- version: "2.0.0" + state: ratified + ratification_date: null diff --git a/arch/ext/Zihpm.yaml b/arch/ext/Zihpm.yaml index d647d5958..6b6da5dab 100644 --- a/arch/ext/Zihpm.yaml +++ b/arch/ext/Zihpm.yaml @@ -1,12 +1,14 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zihpm: - long_name: Programmable hardware performance counters - description: Programmable hardware performance counters - type: unprivileged - versions: - - version: "2.0.0" - state: ratified - ratification_date: unknown - requires: - name: Smhpm \ No newline at end of file +$schema: "ext_schema.json#" +kind: extension +name: Zihpm +long_name: Programmable hardware performance counters +description: Programmable hardware performance counters +type: unprivileged +versions: +- version: "2.0.0" + state: ratified + ratification_date: unknown + requires: + name: Smhpm \ No newline at end of file diff --git a/arch/ext/Zkt.yaml b/arch/ext/Zkt.yaml index 5202b1e19..df11a4e36 100644 --- a/arch/ext/Zkt.yaml +++ b/arch/ext/Zkt.yaml @@ -1,361 +1,363 @@ # yaml-language-server: $schema=../../schemas/ext_schema.json -Zkt: - long_name: Data-independent execution latency - description: | - The Zkt extension attests that the machine has data-independent execution time for a safe - subset of instructions. - This property is commonly called "constant-time" although should not be taken with that literal - meaning. - - All currently proposed cryptographic instructions (scalar `K` extension) are on this list, - together with a set of relevant supporting instructions from `I`, `M`, `C`, and `B` extensions. - - [NOTE] - Failure to prevent leakage of sensitive parameters via the direct timing channel is considered - a serious security vulnerability and will typically result in a CERT CVE security advisory. - - == Scope and Goal - - An "ISA contract" is made between a programmer and the RISC-V implementation that Zkt - instructions do not leak information about processed secret data (plaintext, keying - information, or other "sensitive security parameters" -- FIPS 140-3 term) through differences - in execution latency. - Zkt does _not_ define a set of instructions available in the core; - it just restricts the behaviour of certain instructions if those are implemented. - - Currently, the scope of this document is within scalar RV32/RV64 processors. - Vector cryptography instructions (and appropriate vector support instructions) will be added - later, as will other security-related functions that wish to assert leakage-free execution - latency properties. - - Loads, stores, conditional branches are excluded, along with a set of instructions that are - rarely necessary to process secret data. - Also excluded are instructions for which workarounds exist in standard cryptographic middleware - due to the limitations of other ISA processors. - - The stated goal is that OpenSSL, BoringSSL (Android), the Linux Kernel, and similar trusted - software will not have directly observable timing side channels when compiled and running on a - `Zkt`-enabled RISC-V target. - The Zkt extension explicitly states many of the common latency assumptions made by - cryptography developers. - - Vendors do not have to implement all of the list's instructions to be Zkt compliant; - however, if they claim to have Zkt and implement any of the listed instructions, - it must have data-independent latency. - - For example, many simple RV32I and RV64I cores (without Multiply, Compressed, Bitmanip, or - Cryptographic extensions) are technically compliant with Zkt. - A constant-time AES can be implemented on them using "bit-slice" techniques, - but it will be excruciatingly slow when compared to implementation with AES instructions. - There are no guarantees that even a bit-sliced cipher implementation (largely based on boolean - logic instructions) is secure on a core without Zkt attestation. - - Out-of-order implementations adhering to Zkt are still free to fuse, crack, change or even - ignore sequences of instructions, so long as the optimisations are applied deterministically, - and not based on operand data. - The guiding principle should be that no information about the data being operated on should be - leaked based on the execution latency. - - [NOTE] - It is left to future extensions or other techniques to tackle the problem of data-independent - execution in implementations which advanced out-of-order capabilities which use value - prediction, or which are otherwise data-dependent. - - .Note to software developers - [WARNING,caption="SH"] - ==== - Programming techniques can only mitigate leakage directly caused by - arithmetic, caches, and branches. Other ISAs have had micro-architectural - issues such as Spectre, Meltdown, Speculative Store Bypass, Rogue System - Register Read, Lazy FP State Restore, Bounds Check Bypass Store, TLBleed, - and L1TF/Foreshadow, etc. See e.g. - link:https://github.com/nsacyber/Hardware-and-Firmware-Security-Guidance[NSA Hardware and Firmware Security Guidance] - - It is not within the remit of this proposal to mitigate these - _micro-architectural_ leakages. - ==== - - == Background - - * Timing attacks are much more powerful than was realised before the 2010s, - which has led to a significant mitigation effort in current cryptographic - code-bases. - * Cryptography developers use static and dynamic security testing tools - to trace the handling of secret information and detect occasions where it - influences a branch or is used for a table lookup. - * Architectural testing for Zkt can be pragmatic and semi-formal; - _security by design_ against basic timing attacks can usually be achieved via - conscious implementation (of relevant iterative multi-cycle instructions or - instructions composed of micro-ops) in way that avoids data-dependent latency. - * Laboratory testing may utilize statistical timing attack leakage analysis - techniques such as those described in ISO/IEC 17825 cite:[IS16]. - * Binary executables should not contain secrets in the instruction encodings - (Kerckhoffs's principle), so instruction timing may leak information about - immediates, ordering of input registers, etc. There may be an exception to this - in systems where a binary loader modifies the executable for purposes of - relocation -- and it is desirable to keep the execution location (PC) secret. - This is why instructions such as LUI, AUIPC, and ADDI are on the list. - * The rules used by audit tools are relatively simple to understand. - Very briefly; we call the plaintext, secret keys, expanded keys, nonces, - and other such variables "secrets". A secret variable (arithmetically) - modifying any other variable/register turns that into a secret too. - If a secret ends up in address calculation affecting a load or store, that - is a violation. If a secret affects a branch's condition, that is also a - violation. A secret variable location or register becomes a non-secret via - specific zeroization/sanitisation or by being declared ciphertext - (or otherwise no-longer-secret information). In essence, secrets can only - "touch" instructions on the Zkt list while they are secrets. - - == Specific Instruction Rationale - - * HINT instruction forms (typically encodings with `rd=x0`) are excluded from - the data-independent time requirement. - * Floating point (F, D, Q, L extensions) are currently excluded from the - constant-time requirement as they have very few applications in standardised - cryptography. We may consider adding floating point add, sub, multiply as a - constant time requirement for some floating point extension in case a specific - algorithm (such as the PQC Signature algorithm Falcon) becomes critical. - * Cryptographers typically assume division to be variable-time (while - multiplication is constant time) and implement their Montgomery reduction - routines with that assumption. - * Zicsr, Zifencei are excluded. - * Some instructions are on the list simply because we see no harm in - including them in testing scope. - - == Programming Information - - For background information on secure programming "models", see: - - * Thomas Pornin: _"Why Constant-Time Crypto?"_ (A great introduction to timing assumptions.) https://www.bearssl.org/constanttime.html - * Jean-Philippe Aumasson: _"Guidelines for low-level cryptography software."_ - (A list of recommendations.) https://github.com/veorq/cryptocoding - * Peter Schwabe: _"Timing Attacks and Countermeasures."_ - (Lecture slides -- nice references.) - https://summerschool-croatia.cs.ru.nl/2016/slides/PeterSchwabe.pdf - * Adam Langley: _"ctgrind."_ (This is from 2010 but is still relevant.) - https://www.imperialviolet.org/2010/04/01/ctgrind.html - * Kris Kwiatkowski: _"Constant-time code verification with Memory Sanitizer."_ - https://www.amongbytes.com/post/20210709-testing-constant-time/ - * For early examples of timing attack vulnerabilities, see - https://www.kb.cert.org/vuls/id/997481 and related academic papers. - - == Zkt listings - - The following instructions are included in the `Zkt` subset - They are listed here grouped by their original parent extension. - - .Note to implementers - [NOTE, caption="SH"] - ==== - You do not need to implement all of these instructions to implement `Zkt`. - Rather, every one of these instructions that the core does implement must - adhere to the requirements of `Zkt`. - ==== - - === RVI (Base Instruction Set) - - Only basic arithmetic and `slt*` (for carry computations) are included. - The data-independent timing requirement does not apply to HINT instruction - encoding forms of these instructions. - - [%header,cols="^1,^1,4,8"] - |=== - |RV32 - |RV64 - |Mnemonic - |Instruction - - | ✓ | ✓ | lui _rd_, _imm_ | 'lui' - | ✓ | ✓ | auipc _rd_, _imm_ | 'auipc' - | ✓ | ✓ | addi _rd_, _rs1_, _imm_ | 'addi' - | ✓ | ✓ | slti _rd_, _rs1_, _imm_ | 'slti' - | ✓ | ✓ | sltiu _rd_, _rs1_, _imm_ | 'sltiu' - | ✓ | ✓ | xori _rd_, _rs1_, _imm_ | 'xori' - | ✓ | ✓ | ori _rd_, _rs1_, _imm_ | 'ori' - | ✓ | ✓ | andi _rd_, _rs1_, _imm_ | 'andi' - | ✓ | ✓ | slli _rd_, _rs1_, _imm_ | 'slli' - | ✓ | ✓ | srli _rd_, _rs1_, _imm_ | 'srli' - | ✓ | ✓ | srai _rd_, _rs1_, _imm_ | 'srai' - | ✓ | ✓ | add _rd_, _rs1_, _rs2_ | 'add' - | ✓ | ✓ | sub _rd_, _rs1_, _rs2_ | 'sub' - | ✓ | ✓ | sll _rd_, _rs1_, _rs2_ | 'sll' - | ✓ | ✓ | slt _rd_, _rs1_, _rs2_ | 'slt' - | ✓ | ✓ | sltu _rd_, _rs1_, _rs2_ | 'sltu' - | ✓ | ✓ | xor _rd_, _rs1_, _rs2_ | 'xor' - | ✓ | ✓ | srl _rd_, _rs1_, _rs2_ | 'srl' - | ✓ | ✓ | sra _rd_, _rs1_, _rs2_ | 'sra' - | ✓ | ✓ | or _rd_, _rs1_, _rs2_ | 'or' - | ✓ | ✓ | and _rd_, _rs1_, _rs2_ | 'and' - | | ✓ | addiw _rd_, _rs1_, _imm_ | 'addiw' - | | ✓ | slliw _rd_, _rs1_, _imm_ | 'slliw' - | | ✓ | srliw _rd_, _rs1_, _imm_ | 'srliw' - | | ✓ | sraiw _rd_, _rs1_, _imm_ | 'sraiw' - | | ✓ | addw _rd_, _rs1_, _rs2_ | 'addw' - | | ✓ | subw _rd_, _rs1_, _rs2_ | 'subw' - | | ✓ | sllw _rd_, _rs1_, _rs2_ | 'sllw' - | | ✓ | srlw _rd_, _rs1_, _rs2_ | 'srlw' - | | ✓ | sraw _rd_, _rs1_, _rs2_ | 'sraw' - |=== - - === RVM (Multiply) - - Multiplication is included; division and remaindering excluded. - - [%header,cols="^1,^1,4,8"] - |=== - |RV32 - |RV64 - |Mnemonic - |Instruction - - | ✓ | ✓ | mul _rd_, _rs1_, _rs2_ | 'mul' - | ✓ | ✓ | mulh _rd_, _rs1_, _rs2_ | 'mulh' - | ✓ | ✓ | mulhsu _rd_, _rs1_, _rs2_ | 'mulhsu' - | ✓ | ✓ | mulhu _rd_, _rs1_, _rs2_ | 'mulhu' - | | ✓ | mulw _rd_, _rs1_, _rs2_ | 'mulw' - |=== - - === RVC (Compressed) - - Same criteria as in RVI. Organised by quadrants. - - [%header,cols="^1,^1,4,8"] - |=== - |RV32 - |RV64 - |Mnemonic - |Instruction - - | ✓ | ✓ | c.nop | 'c_nop' - | ✓ | ✓ | c.addi | 'c_addi' - | | ✓ | c.addiw | 'c_addiw' - | ✓ | ✓ | c.lui | 'c_lui' - | ✓ | ✓ | c.srli | 'c_srli' - | ✓ | ✓ | c.srai | 'c_srai' - | ✓ | ✓ | c.andi | 'c_andi' - | ✓ | ✓ | c.sub | 'c_sub' - | ✓ | ✓ | c.xor | 'c_xor' - | ✓ | ✓ | c.or | 'c_or' - | ✓ | ✓ | c.and | 'c_and' - | | ✓ | c.subw | 'c_subw' - | | ✓ | c.addw | 'c_addw' - | ✓ | ✓ | c.slli | 'c_slli' - | ✓ | ✓ | c.mv | 'c_mv' - | ✓ | ✓ | c.add | 'c_add' - |=== - - === RVK (Scalar Cryptography) - - All K-specific instructions are included. - Additionally, `seed` CSR latency should be independent of `ES16` state output - `entropy` bits, as that is a sensitive security parameter. - See <(virtual_address, X[rs2], AmoOperation::Add, aq, rl, $encoding); + X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Add, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -129,12 +130,13 @@ amoadd.d: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amoadd.w.yaml b/arch/inst/A/amoadd.w.yaml index 6080ae954..6a70c42fb 100644 --- a/arch/inst/A/amoadd.w.yaml +++ b/arch/inst/A/amoadd.w.yaml @@ -1,125 +1,126 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoadd.w: - long_name: Atomic fetch-and-add word - description: | - Atomically: - - * Load the word at address _rs1_ - * Write the sign-extended value into _rd_ - * Add the least-significant word of register _rs2_ to the loaded value - * Write the sum to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - assembly: xd, xs2, (xrs1) - encoding: - match: 00000------------010-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.w +long_name: Atomic fetch-and-add word +description: | + Atomically: + + * Load the word at address _rs1_ + * Write the sign-extended value into _rd_ + * Add the least-significant word of register _rs2_ to the loaded value + * Write the sum to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +assembly: xd, xs2, (xrs1) +encoding: + match: 00000------------010-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Add, aq, rl, $encoding); + X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Add, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -128,12 +129,13 @@ amoadd.w: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amoand.d.yaml b/arch/inst/A/amoand.d.yaml index 5c8742375..ae9d8dcfd 100644 --- a/arch/inst/A/amoand.d.yaml +++ b/arch/inst/A/amoand.d.yaml @@ -1,126 +1,127 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoand.d: - long_name: Atomic fetch-and-and doubleword - description: | - Atomically: - - * Load the doubleword at address _rs1_ - * Write the loaded value into _rd_ - * AND the value of register _rs2_ to the loaded value - * Write the result to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - base: 64 - assembly: xd, xs2, (xrs1) - encoding: - match: 01100------------011-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amoand.d +long_name: Atomic fetch-and-and doubleword +description: | + Atomically: + + * Load the doubleword at address _rs1_ + * Write the loaded value into _rd_ + * AND the value of register _rs2_ to the loaded value + * Write the result to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +base: 64 +assembly: xd, xs2, (xrs1) +encoding: + match: 01100------------011-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::And, aq, rl, $encoding); + X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::And, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -129,12 +130,13 @@ amoand.d: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amoand.w.yaml b/arch/inst/A/amoand.w.yaml index 35c15e393..485105d4f 100644 --- a/arch/inst/A/amoand.w.yaml +++ b/arch/inst/A/amoand.w.yaml @@ -1,125 +1,126 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoand.w: - long_name: Atomic fetch-and-and word - description: | - Atomically: - - * Load the word at address _rs1_ - * Write the sign-extended value into _rd_ - * AND the least-significant word of register _rs2_ to the loaded value - * Write the result to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - assembly: xd, xs2, (xrs1) - encoding: - match: 01100------------010-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amoand.w +long_name: Atomic fetch-and-and word +description: | + Atomically: + + * Load the word at address _rs1_ + * Write the sign-extended value into _rd_ + * AND the least-significant word of register _rs2_ to the loaded value + * Write the result to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +assembly: xd, xs2, (xrs1) +encoding: + match: 01100------------010-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::And, aq, rl, $encoding); + X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::And, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -128,12 +129,13 @@ amoand.w: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amomax.d.yaml b/arch/inst/A/amomax.d.yaml index 2d5af2619..a5c110988 100644 --- a/arch/inst/A/amomax.d.yaml +++ b/arch/inst/A/amomax.d.yaml @@ -1,126 +1,127 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amomax.d: - long_name: Atomic MAX doubleword - description: | - Atomically: - - * Load the doubleword at address _rs1_ - * Write the loaded value into _rd_ - * Signed compare the value of register _rs2_ to the loaded value, and select the maximum value - * Write the maximum to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - base: 64 - assembly: xd, xs2, (xrs1) - encoding: - match: 10100------------011-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amomax.d +long_name: Atomic MAX doubleword +description: | + Atomically: + + * Load the doubleword at address _rs1_ + * Write the loaded value into _rd_ + * Signed compare the value of register _rs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +base: 64 +assembly: xd, xs2, (xrs1) +encoding: + match: 10100------------011-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Max, aq, rl, $encoding); + X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Max, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -129,12 +130,13 @@ amomax.d: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amomax.w.yaml b/arch/inst/A/amomax.w.yaml index 6cdf9bbbb..b8a5b4db7 100644 --- a/arch/inst/A/amomax.w.yaml +++ b/arch/inst/A/amomax.w.yaml @@ -1,125 +1,126 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amomax.w: - long_name: Atomic MAX word - description: | - Atomically: - - * Load the word at address _rs1_ - * Write the sign-extended value into _rd_ - * Signed compare the least-significant word of register _rs2_ to the loaded value, and select the maximum value - * Write the maximum to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - assembly: xd, xs2, (xrs1) - encoding: - match: 10100------------010-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amomax.w +long_name: Atomic MAX word +description: | + Atomically: + + * Load the word at address _rs1_ + * Write the sign-extended value into _rd_ + * Signed compare the least-significant word of register _rs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +assembly: xd, xs2, (xrs1) +encoding: + match: 10100------------010-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Max, aq, rl, $encoding); + X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Max, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -128,12 +129,13 @@ amomax.w: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amomaxu.d.yaml b/arch/inst/A/amomaxu.d.yaml index 783696bf0..7ccf572b0 100644 --- a/arch/inst/A/amomaxu.d.yaml +++ b/arch/inst/A/amomaxu.d.yaml @@ -1,125 +1,126 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amomaxu.d: - long_name: Atomic MAX unsigned doubleword - description: | - Atomically: - - * Load the doubleword at address _rs1_ - * Write the loaded value into _rd_ - * Unsigned compare the value of register _rs2_ to the loaded value, and select the maximum value - * Write the maximum to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - base: 64 - assembly: xd, xs2, (xrs1) - encoding: - match: 11100------------011-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - XReg virtual_address = X[rs1]; +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.d +long_name: Atomic MAX unsigned doubleword +description: | + Atomically: + + * Load the doubleword at address _rs1_ + * Write the loaded value into _rd_ + * Unsigned compare the value of register _rs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +base: 64 +assembly: xd, xs2, (xrs1) +encoding: + match: 11100------------011-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + XReg virtual_address = X[rs1]; - X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Maxu, aq, rl, $encoding); + X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Maxu, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -128,12 +129,13 @@ amomaxu.d: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amomaxu.w.yaml b/arch/inst/A/amomaxu.w.yaml index 6ff880c59..555a689c9 100644 --- a/arch/inst/A/amomaxu.w.yaml +++ b/arch/inst/A/amomaxu.w.yaml @@ -1,125 +1,126 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amomaxu.w: - long_name: Atomic MAX unsigned word - description: | - Atomically: - - * Load the word at address _rs1_ - * Write the sign-extended value into _rd_ - * Unsigned compare the least-significant word of register _rs2_ to the loaded value, and select the maximum value - * Write the maximum to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - assembly: xd, xs2, (xrs1) - encoding: - match: 11100------------010-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.w +long_name: Atomic MAX unsigned word +description: | + Atomically: + + * Load the word at address _rs1_ + * Write the sign-extended value into _rd_ + * Unsigned compare the least-significant word of register _rs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +assembly: xd, xs2, (xrs1) +encoding: + match: 11100------------010-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Maxu, aq, rl, $encoding); + X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Maxu, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -128,12 +129,13 @@ amomaxu.w: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amomin.d.yaml b/arch/inst/A/amomin.d.yaml index 2efad276b..367ae39b1 100644 --- a/arch/inst/A/amomin.d.yaml +++ b/arch/inst/A/amomin.d.yaml @@ -1,126 +1,127 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amomin.d: - long_name: Atomic MIN doubleword - description: | - Atomically: - - * Load the doubleword at address _rs1_ - * Write the loaded value into _rd_ - * Signed compare the value of register _rs2_ to the loaded value, and select the mimimum value - * Write the minimum to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - base: 64 - assembly: xd, xs2, (xrs1) - encoding: - match: 10000------------011-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amomin.d +long_name: Atomic MIN doubleword +description: | + Atomically: + + * Load the doubleword at address _rs1_ + * Write the loaded value into _rd_ + * Signed compare the value of register _rs2_ to the loaded value, and select the mimimum value + * Write the minimum to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +base: 64 +assembly: xd, xs2, (xrs1) +encoding: + match: 10000------------011-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Min, aq, rl, $encoding); + X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Min, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -129,12 +130,13 @@ amomin.d: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amomin.w.yaml b/arch/inst/A/amomin.w.yaml index e614e863e..3890b056c 100644 --- a/arch/inst/A/amomin.w.yaml +++ b/arch/inst/A/amomin.w.yaml @@ -1,125 +1,126 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amomin.w: - long_name: Atomic MIN word - description: | - Atomically: - - * Load the word at address _rs1_ - * Write the sign-extended value into _rd_ - * Signed compare the least-significant word of register _rs2_ to the loaded value, and select the mimimum value - * Write the result to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - assembly: xd, xs2, (xrs1) - encoding: - match: 10000------------010-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amomin.w +long_name: Atomic MIN word +description: | + Atomically: + + * Load the word at address _rs1_ + * Write the sign-extended value into _rd_ + * Signed compare the least-significant word of register _rs2_ to the loaded value, and select the mimimum value + * Write the result to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +assembly: xd, xs2, (xrs1) +encoding: + match: 10000------------010-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Min, aq, rl, $encoding); + X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Min, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -128,12 +129,13 @@ amomin.w: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amominu.d.yaml b/arch/inst/A/amominu.d.yaml index d83baf6e2..8bfc19055 100644 --- a/arch/inst/A/amominu.d.yaml +++ b/arch/inst/A/amominu.d.yaml @@ -1,126 +1,127 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amominu.d: - long_name: Atomic MIN unsigned doubleword - description: | - Atomically: - - * Load the doubleword at address _rs1_ - * Write the loaded value into _rd_ - * Unsigned compare the value of register _rs2_ to the loaded value, and select the mimimum value - * Write the minimum to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - base: 64 - assembly: xd, xs2, (xrs1) - encoding: - match: 11000------------011-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amominu.d +long_name: Atomic MIN unsigned doubleword +description: | + Atomically: + + * Load the doubleword at address _rs1_ + * Write the loaded value into _rd_ + * Unsigned compare the value of register _rs2_ to the loaded value, and select the mimimum value + * Write the minimum to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +base: 64 +assembly: xd, xs2, (xrs1) +encoding: + match: 11000------------011-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Minu, aq, rl, $encoding); + X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Minu, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -129,12 +130,13 @@ amominu.d: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amominu.w.yaml b/arch/inst/A/amominu.w.yaml index e292c16a4..6f41b3c64 100644 --- a/arch/inst/A/amominu.w.yaml +++ b/arch/inst/A/amominu.w.yaml @@ -1,125 +1,126 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amominu.w: - long_name: Atomic MIN unsigned word - description: | - Atomically: - - * Load the word at address _rs1_ - * Write the sign-extended value into _rd_ - * Unsigned compare the least-significant word of register _rs2_ to the loaded word, and select the mimimum value - * Write the result to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - assembly: xd, xs2, (xrs1) - encoding: - match: 11000------------010-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amominu.w +long_name: Atomic MIN unsigned word +description: | + Atomically: + + * Load the word at address _rs1_ + * Write the sign-extended value into _rd_ + * Unsigned compare the least-significant word of register _rs2_ to the loaded word, and select the mimimum value + * Write the result to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +assembly: xd, xs2, (xrs1) +encoding: + match: 11000------------010-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Minu, aq, rl, $encoding); + X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Minu, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -128,12 +129,13 @@ amominu.w: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amoor.d.yaml b/arch/inst/A/amoor.d.yaml index c3e2cb048..63783db75 100644 --- a/arch/inst/A/amoor.d.yaml +++ b/arch/inst/A/amoor.d.yaml @@ -1,126 +1,127 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoor.d: - long_name: Atomic fetch-and-or doubleword - description: | - Atomically: - - * Load the doubleword at address _rs1_ - * Write the loaded value into _rd_ - * OR the value of register _rs2_ to the loaded value - * Write the result to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - base: 64 - assembly: xd, xs2, (xrs1) - encoding: - match: 01000------------011-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amoor.d +long_name: Atomic fetch-and-or doubleword +description: | + Atomically: + + * Load the doubleword at address _rs1_ + * Write the loaded value into _rd_ + * OR the value of register _rs2_ to the loaded value + * Write the result to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +base: 64 +assembly: xd, xs2, (xrs1) +encoding: + match: 01000------------011-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Or, aq, rl, $encoding); + X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Or, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -129,12 +130,13 @@ amoor.d: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amoor.w.yaml b/arch/inst/A/amoor.w.yaml index 208f5489c..ecde879fa 100644 --- a/arch/inst/A/amoor.w.yaml +++ b/arch/inst/A/amoor.w.yaml @@ -1,125 +1,126 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoor.w: - long_name: Atomic fetch-and-or word - description: | - Atomically: - - * Load the word at address _rs1_ - * Write the sign-extended value into _rd_ - * OR the least-significant word of register _rs2_ to the loaded value - * Write the result to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - assembly: xd, xs2, (xrs1) - encoding: - match: 01000------------010-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amoor.w +long_name: Atomic fetch-and-or word +description: | + Atomically: + + * Load the word at address _rs1_ + * Write the sign-extended value into _rd_ + * OR the least-significant word of register _rs2_ to the loaded value + * Write the result to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +assembly: xd, xs2, (xrs1) +encoding: + match: 01000------------010-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Or, aq, rl, $encoding); + X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Or, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -128,12 +129,13 @@ amoor.w: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amoswap.d.yaml b/arch/inst/A/amoswap.d.yaml index e7c3990a8..6fe322a4c 100644 --- a/arch/inst/A/amoswap.d.yaml +++ b/arch/inst/A/amoswap.d.yaml @@ -1,125 +1,126 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoswap.d: - long_name: Atomic SWAP doubleword - description: | - Atomically: - - * Load the doubleword at address _rs1_ - * Write the value into _rd_ - * Store the value of register _rs2_ to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - base: 64 - assembly: xd, xs2, (xrs1) - encoding: - match: 00001------------011-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.d +long_name: Atomic SWAP doubleword +description: | + Atomically: + + * Load the doubleword at address _rs1_ + * Write the value into _rd_ + * Store the value of register _rs2_ to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +base: 64 +assembly: xd, xs2, (xrs1) +encoding: + match: 00001------------011-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Swap, aq, rl, $encoding); + X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Swap, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -128,12 +129,13 @@ amoswap.d: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amoswap.w.yaml b/arch/inst/A/amoswap.w.yaml index 0fc4bbcdb..224a7d173 100644 --- a/arch/inst/A/amoswap.w.yaml +++ b/arch/inst/A/amoswap.w.yaml @@ -1,124 +1,125 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoswap.w: - long_name: Atomic SWAP word - description: | - Atomically: - - * Load the word at address _rs1_ - * Write the sign-extended value into _rd_ - * Store the least-significant word of register _rs2_ to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - assembly: xd, xs2, (xrs1) - encoding: - match: 00001------------010-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.w +long_name: Atomic SWAP word +description: | + Atomically: + + * Load the word at address _rs1_ + * Write the sign-extended value into _rd_ + * Store the least-significant word of register _rs2_ to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +assembly: xd, xs2, (xrs1) +encoding: + match: 00001------------010-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Swap, aq, rl, $encoding); + X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Swap, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -127,12 +128,13 @@ amoswap.w: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amoxor.d.yaml b/arch/inst/A/amoxor.d.yaml index 7050c9146..fecb96843 100644 --- a/arch/inst/A/amoxor.d.yaml +++ b/arch/inst/A/amoxor.d.yaml @@ -1,126 +1,127 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoxor.d: - long_name: Atomic fetch-and-xor doubleword - description: | - Atomically: - - * Load the doubleword at address _rs1_ - * Write the loaded value into _rd_ - * XOR the value of register _rs2_ to the loaded value - * Write the result to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - base: 64 - assembly: xd, xs2, (xrs1) - encoding: - match: 00100------------011-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.d +long_name: Atomic fetch-and-xor doubleword +description: | + Atomically: + + * Load the doubleword at address _rs1_ + * Write the loaded value into _rd_ + * XOR the value of register _rs2_ to the loaded value + * Write the result to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +base: 64 +assembly: xd, xs2, (xrs1) +encoding: + match: 00100------------011-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Xor, aq, rl, $encoding); + X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Xor, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -129,12 +130,13 @@ amoxor.d: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/amoxor.w.yaml b/arch/inst/A/amoxor.w.yaml index ba8eeaea4..e299f6350 100644 --- a/arch/inst/A/amoxor.w.yaml +++ b/arch/inst/A/amoxor.w.yaml @@ -1,125 +1,126 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoxor.w: - long_name: Atomic fetch-and-xor word - description: | - Atomically: - - * Load the word at address _rs1_ - * Write the sign-extended value into _rd_ - * XOR the least-significant word of register _rs2_ to the loaded value - * Write the result to the address in _rs1_ - definedBy: - anyOf: [A, Zaamo] - assembly: xd, xs2, (xrs1) - encoding: - match: 00100------------010-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.w +long_name: Atomic fetch-and-xor word +description: | + Atomically: + + * Load the word at address _rs1_ + * Write the sign-extended value into _rd_ + * XOR the least-significant word of register _rs2_ to the loaded value + * Write the result to the address in _rs1_ +definedBy: + anyOf: [A, Zaamo] +assembly: xd, xs2, (xrs1) +encoding: + match: 00100------------010-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1]; + XReg virtual_address = X[rs1]; - X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Xor, aq, rl, $encoding); + X[rd] = amo<32>(virtual_address, X[rs2][31:0], AmoOperation::Xor, aq, rl, $encoding); - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -128,12 +129,13 @@ amoxor.w: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/lr.d.yaml b/arch/inst/A/lr.d.yaml index ac83deb23..ca7b2288e 100644 --- a/arch/inst/A/lr.d.yaml +++ b/arch/inst/A/lr.d.yaml @@ -1,139 +1,141 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -lr.d: - long_name: Load reserved doubleword - description: | - Loads a word from the address in rs1, places the value in rd, - and registers a _reservation set_ -- a set of bytes that subsumes the bytes in the - addressed word. - - The address in rs1 must be 8-byte aligned. - - If the address is not naturally aligned, a `LoadAddressMisaligned` exception or an - `LoadAccessFault` exception will be generated. The access-fault exception can be generated - for a memory access that would otherwise be able to complete except for the misalignment, - if the misaligned access should not be emulated. - - An implementation can register an arbitrarily large reservation set on each LR, provided the - reservation set includes all bytes of the addressed data word or doubleword. - An SC can only pair with the most recent LR in program order. - An SC may succeed only if no store from another hart to the reservation set can be - observed to have occurred between the LR and the SC, and if there is no other SC between the - LR and itself in program order. - An SC may succeed only if no write from a device other than a hart to the bytes accessed by - the LR instruction can be observed to have occurred between the LR and SC. Note this LR - might have had a different effective address and data size, but reserved the SC's - address as part of the reservation set. - - [NOTE] - ---- - Following this model, in systems with memory translation, an SC is allowed to succeed if the - earlier LR reserved the same location using an alias with a different virtual address, but is - also allowed to fail if the virtual address is different. - - To accommodate legacy devices and buses, writes from devices other than RISC-V harts are only - required to invalidate reservations when they overlap the bytes accessed by the LR. - These writes are not required to invalidate the reservation when they access other bytes in - the reservation set. - ---- - - Software should not set the _rl_ bit on an LR instruction unless the _aq_ bit is also set. - LR.rl and SC.aq instructions are not guaranteed to provide any stronger ordering than those - with both bits clear, but may result in lower performance. - definedBy: - anyOf: [A, Zalrsc] - base: 64 - assembly: xd, xs1 - encoding: - match: 00010--00000-----011-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); +$schema: "inst_schema.json#" +kind: instruction +name: lr.d +long_name: Load reserved doubleword +description: | + Loads a word from the address in rs1, places the value in rd, + and registers a _reservation set_ -- a set of bytes that subsumes the bytes in the + addressed word. + + The address in rs1 must be 8-byte aligned. + + If the address is not naturally aligned, a `LoadAddressMisaligned` exception or an + `LoadAccessFault` exception will be generated. The access-fault exception can be generated + for a memory access that would otherwise be able to complete except for the misalignment, + if the misaligned access should not be emulated. + + An implementation can register an arbitrarily large reservation set on each LR, provided the + reservation set includes all bytes of the addressed data word or doubleword. + An SC can only pair with the most recent LR in program order. + An SC may succeed only if no store from another hart to the reservation set can be + observed to have occurred between the LR and the SC, and if there is no other SC between the + LR and itself in program order. + An SC may succeed only if no write from a device other than a hart to the bytes accessed by + the LR instruction can be observed to have occurred between the LR and SC. Note this LR + might have had a different effective address and data size, but reserved the SC's + address as part of the reservation set. + + [NOTE] + ---- + Following this model, in systems with memory translation, an SC is allowed to succeed if the + earlier LR reserved the same location using an alias with a different virtual address, but is + also allowed to fail if the virtual address is different. + + To accommodate legacy devices and buses, writes from devices other than RISC-V harts are only + required to invalidate reservations when they overlap the bytes accessed by the LR. + These writes are not required to invalidate the reservation when they access other bytes in + the reservation set. + ---- + + Software should not set the _rl_ bit on an LR instruction unless the _aq_ bit is also set. + LR.rl and SC.aq instructions are not guaranteed to provide any stronger ordering than those + with both bits clear, but may result in lower performance. +definedBy: + anyOf: [A, Zalrsc] +base: 64 +assembly: xd, xs1 +encoding: + match: 00010--00000-----011-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1]; + + if (!is_naturally_aligned<64>(virtual_address)) { + # can raise either LoadAddressMisaligned *or* LoadAccessFault + # + # from the spec: + # If the address is not naturally aligned, an address-misaligned exception or + # an access-fault exception will be generated. The access-fault exception can + # be generated for a memory access that would otherwise be able to complete except + # for the misalignment, if the misaligned access should not be emulated. + + if (LRSC_MISALIGNED_BEHAVIOR == "always raise misaligned exception") { + raise(ExceptionCode::LoadAddressMisaligned, effective_ldst_mode(), virtual_address); + } else if (LRSC_MISALIGNED_BEHAVIOR == "always raise access fault") { + raise(ExceptionCode::LoadAccessFault, effective_ldst_mode(), virtual_address); + } else { + unpredictable("Implementations may raise either a LoadAddressMisaligned or a LoadAccessFault when an LR/SC address is misaligned"); } - - XReg virtual_address = X[rs1]; - - if (!is_naturally_aligned<64>(virtual_address)) { - # can raise either LoadAddressMisaligned *or* LoadAccessFault - # - # from the spec: - # If the address is not naturally aligned, an address-misaligned exception or - # an access-fault exception will be generated. The access-fault exception can - # be generated for a memory access that would otherwise be able to complete except - # for the misalignment, if the misaligned access should not be emulated. - - if (LRSC_MISALIGNED_BEHAVIOR == "always raise misaligned exception") { - raise(ExceptionCode::LoadAddressMisaligned, effective_ldst_mode(), virtual_address); - } else if (LRSC_MISALIGNED_BEHAVIOR == "always raise access fault") { - raise(ExceptionCode::LoadAccessFault, effective_ldst_mode(), virtual_address); - } else { - unpredictable("Implementations may raise either a LoadAddressMisaligned or a LoadAccessFault when an LR/SC address is misaligned"); - } - } - - X[rd] = load_reserved<32>(virtual_address, aq, rl, $encoding); - - - - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Extensions might perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - let aligned : bool = - /* BYTE and HALF would only occur due to invalid decodes, but it doesn't hurt - * to treat them as valid here; otherwise we'd need to throw an internal_error. - */ - match width { - BYTE => true, - HALF => vaddr[0..0] == 0b0, - WORD => vaddr[1..0] == 0b00, - DOUBLE => vaddr[2..0] == 0b000 - }; - /* "LR faults like a normal load, even though it's in the AMO major opcode space." - * - Andrew Waterman, isa-dev, 10 Jul 2018. - */ - if not(aligned) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => - match (width, sizeof(xlen)) { - (BYTE, _) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 1, aq, aq & rl, true), false), - (HALF, _) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 2, aq, aq & rl, true), false), - (WORD, _) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 4, aq, aq & rl, true), false), - (DOUBLE, 64) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 8, aq, aq & rl, true), false), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - } - } - } + } + + X[rd] = load_reserved<32>(virtual_address, aq, rl, $encoding); + + + +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Extensions might perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + let aligned : bool = + /* BYTE and HALF would only occur due to invalid decodes, but it doesn't hurt + * to treat them as valid here; otherwise we'd need to throw an internal_error. + */ + match width { + BYTE => true, + HALF => vaddr[0..0] == 0b0, + WORD => vaddr[1..0] == 0b00, + DOUBLE => vaddr[2..0] == 0b000 + }; + /* "LR faults like a normal load, even though it's in the AMO major opcode space." + * - Andrew Waterman, isa-dev, 10 Jul 2018. + */ + if not(aligned) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => + match (width, sizeof(xlen)) { + (BYTE, _) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 1, aq, aq & rl, true), false), + (HALF, _) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 2, aq, aq & rl, true), false), + (WORD, _) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 4, aq, aq & rl, true), false), + (DOUBLE, 64) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 8, aq, aq & rl, true), false), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + } + } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/A/lr.w.yaml b/arch/inst/A/lr.w.yaml index 46442c6b3..0ae9dd0c8 100644 --- a/arch/inst/A/lr.w.yaml +++ b/arch/inst/A/lr.w.yaml @@ -1,148 +1,150 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -lr.w: - long_name: Load reserved word - description: | - Loads a word from the address in rs1, places the sign-extended value in rd, - and registers a _reservation set_ -- a set of bytes that subsumes the bytes in the - addressed word. - - <%- if XLEN == 64 -%> - The 32-bit load result is sign-extended to 64-bits. - <%- end -%> - - The address in rs1 must be naturally aligned to the size of the operand - (_i.e._, eight-byte aligned for doublewords and four-byte aligned for words). - - If the address is not naturally aligned, a `LoadAddressMisaligned` exception or an - `LoadAccessFault` exception will be generated. The access-fault exception can be generated - for a memory access that would otherwise be able to complete except for the misalignment, - if the misaligned access should not be emulated. - - An implementation can register an arbitrarily large reservation set on each LR, provided the - reservation set includes all bytes of the addressed data word or doubleword. - An SC can only pair with the most recent LR in program order. - An SC may succeed only if no store from another hart to the reservation set can be - observed to have occurred between the LR and the SC, and if there is no other SC between the - LR and itself in program order. - An SC may succeed only if no write from a device other than a hart to the bytes accessed by - the LR instruction can be observed to have occurred between the LR and SC. Note this LR - might have had a different effective address and data size, but reserved the SC's - address as part of the reservation set. - - [NOTE] - ---- - Following this model, in systems with memory translation, an SC is allowed to succeed if the - earlier LR reserved the same location using an alias with a different virtual address, but is - also allowed to fail if the virtual address is different. - - To accommodate legacy devices and buses, writes from devices other than RISC-V harts are only - required to invalidate reservations when they overlap the bytes accessed by the LR. - These writes are not required to invalidate the reservation when they access other bytes in - the reservation set. - ---- - - Software should not set the _rl_ bit on an LR instruction unless the _aq_ bit is also set. - LR.rl and SC.aq instructions are not guaranteed to provide any stronger ordering than those - with both bits clear, but may result in lower performance. - definedBy: - anyOf: [A, Zalrsc] - assembly: xd, xs1 - encoding: - match: 00010--00000-----010-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); +$schema: "inst_schema.json#" +kind: instruction +name: lr.w +long_name: Load reserved word +description: | + Loads a word from the address in rs1, places the sign-extended value in rd, + and registers a _reservation set_ -- a set of bytes that subsumes the bytes in the + addressed word. + + <%- if XLEN == 64 -%> + The 32-bit load result is sign-extended to 64-bits. + <%- end -%> + + The address in rs1 must be naturally aligned to the size of the operand + (_i.e._, eight-byte aligned for doublewords and four-byte aligned for words). + + If the address is not naturally aligned, a `LoadAddressMisaligned` exception or an + `LoadAccessFault` exception will be generated. The access-fault exception can be generated + for a memory access that would otherwise be able to complete except for the misalignment, + if the misaligned access should not be emulated. + + An implementation can register an arbitrarily large reservation set on each LR, provided the + reservation set includes all bytes of the addressed data word or doubleword. + An SC can only pair with the most recent LR in program order. + An SC may succeed only if no store from another hart to the reservation set can be + observed to have occurred between the LR and the SC, and if there is no other SC between the + LR and itself in program order. + An SC may succeed only if no write from a device other than a hart to the bytes accessed by + the LR instruction can be observed to have occurred between the LR and SC. Note this LR + might have had a different effective address and data size, but reserved the SC's + address as part of the reservation set. + + [NOTE] + ---- + Following this model, in systems with memory translation, an SC is allowed to succeed if the + earlier LR reserved the same location using an alias with a different virtual address, but is + also allowed to fail if the virtual address is different. + + To accommodate legacy devices and buses, writes from devices other than RISC-V harts are only + required to invalidate reservations when they overlap the bytes accessed by the LR. + These writes are not required to invalidate the reservation when they access other bytes in + the reservation set. + ---- + + Software should not set the _rl_ bit on an LR instruction unless the _aq_ bit is also set. + LR.rl and SC.aq instructions are not guaranteed to provide any stronger ordering than those + with both bits clear, but may result in lower performance. +definedBy: + anyOf: [A, Zalrsc] +assembly: xd, xs1 +encoding: + match: 00010--00000-----010-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1]; + + if (!is_naturally_aligned<32>(virtual_address)) { + # can raise either LoadAddressMisaligned *or* LoadAccessFault + # + # from the spec: + # If the address is not naturally aligned, an address-misaligned exception or + # an access-fault exception will be generated. The access-fault exception can + # be generated for a memory access that would otherwise be able to complete except + # for the misalignment, if the misaligned access should not be emulated. + + if (LRSC_MISALIGNED_BEHAVIOR == "always raise misaligned exception") { + raise(ExceptionCode::LoadAddressMisaligned, effective_ldst_mode(), virtual_address); + } else if (LRSC_MISALIGNED_BEHAVIOR == "always raise access fault") { + raise(ExceptionCode::LoadAccessFault, effective_ldst_mode(), virtual_address); + } else { + unpredictable("Implementations may raise either a LoadAddressMisaligned or a LoadAccessFault when an LR/SC address is misaligned"); } - - XReg virtual_address = X[rs1]; - - if (!is_naturally_aligned<32>(virtual_address)) { - # can raise either LoadAddressMisaligned *or* LoadAccessFault - # - # from the spec: - # If the address is not naturally aligned, an address-misaligned exception or - # an access-fault exception will be generated. The access-fault exception can - # be generated for a memory access that would otherwise be able to complete except - # for the misalignment, if the misaligned access should not be emulated. - - if (LRSC_MISALIGNED_BEHAVIOR == "always raise misaligned exception") { - raise(ExceptionCode::LoadAddressMisaligned, effective_ldst_mode(), virtual_address); - } else if (LRSC_MISALIGNED_BEHAVIOR == "always raise access fault") { - raise(ExceptionCode::LoadAccessFault, effective_ldst_mode(), virtual_address); - } else { - unpredictable("Implementations may raise either a LoadAddressMisaligned or a LoadAccessFault when an LR/SC address is misaligned"); + } + + XReg load_value = load_reserved<32>(virtual_address, aq, rl, $encoding); + if (xlen() == 64) { + X[rd] = load_value; + } else { + X[rd] = sext(load_value[31:0], 32); + } + + + +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Extensions might perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + let aligned : bool = + /* BYTE and HALF would only occur due to invalid decodes, but it doesn't hurt + * to treat them as valid here; otherwise we'd need to throw an internal_error. + */ + match width { + BYTE => true, + HALF => vaddr[0..0] == 0b0, + WORD => vaddr[1..0] == 0b00, + DOUBLE => vaddr[2..0] == 0b000 + }; + /* "LR faults like a normal load, even though it's in the AMO major opcode space." + * - Andrew Waterman, isa-dev, 10 Jul 2018. + */ + if not(aligned) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => + match (width, sizeof(xlen)) { + (BYTE, _) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 1, aq, aq & rl, true), false), + (HALF, _) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 2, aq, aq & rl, true), false), + (WORD, _) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 4, aq, aq & rl, true), false), + (DOUBLE, 64) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 8, aq, aq & rl, true), false), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + } + } + } } - } - - XReg load_value = load_reserved<32>(virtual_address, aq, rl, $encoding); - if (xlen() == 64) { - X[rd] = load_value; } else { - X[rd] = sext(load_value[31:0], 32); + handle_illegal(); + RETIRE_FAIL } + } - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Extensions might perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - let aligned : bool = - /* BYTE and HALF would only occur due to invalid decodes, but it doesn't hurt - * to treat them as valid here; otherwise we'd need to throw an internal_error. - */ - match width { - BYTE => true, - HALF => vaddr[0..0] == 0b0, - WORD => vaddr[1..0] == 0b00, - DOUBLE => vaddr[2..0] == 0b000 - }; - /* "LR faults like a normal load, even though it's in the AMO major opcode space." - * - Andrew Waterman, isa-dev, 10 Jul 2018. - */ - if not(aligned) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => - match (width, sizeof(xlen)) { - (BYTE, _) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 1, aq, aq & rl, true), false), - (HALF, _) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 2, aq, aq & rl, true), false), - (WORD, _) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 4, aq, aq & rl, true), false), - (DOUBLE, 64) => process_loadres(rd, vaddr, mem_read(Read(Data), addr, 8, aq, aq & rl, true), false), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - } - } - } - } - } else { - handle_illegal(); - RETIRE_FAIL - } - } - - - diff --git a/arch/inst/A/sc.d.yaml b/arch/inst/A/sc.d.yaml index c50aaa021..72a0a79f3 100644 --- a/arch/inst/A/sc.d.yaml +++ b/arch/inst/A/sc.d.yaml @@ -1,217 +1,218 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sc.d: - long_name: Store conditional doubleword - description: | - `sc.d` conditionally writes a doubleword in _rs2_ to the address in _rs1_: - the `sc.d` succeeds only if the reservation is still valid and the - reservation set contains the bytes being written. If the `sc.d` succeeds, - the instruction writes the doubleword in _rs2_ to memory, and it writes zero to _rd_. - If the `sc.d` fails, the instruction does not write to memory, and it writes a - nonzero value to _rd_. For the purposes of memory protection, a failed `sc.d` - may be treated like a store. Regardless of success or failure, executing an - `sc.d` instruction invalidates any reservation held by this hart. - - The failure code with value 1 encodes an unspecified failure. - Other failure codes are reserved at this time. - Portable software should only assume the failure code will be non-zero. - - The address held in _rs1_ must be naturally aligned to the size of the operand - (_i.e._, eight-byte aligned). - If the address is not naturally aligned, an address-misaligned exception or an - access-fault exception will be generated. - The access-fault exception can be generated for a memory access that would otherwise - be able to complete except for the misalignment, - if the misaligned access should not be emulated. - - [NOTE] - -- - Emulating misaligned LR/SC sequences is impractical in most systems. - - Misaligned LR/SC sequences also raise the possibility of accessing multiple - reservation sets at once, which present definitions do not provide for. - -- - - An implementation can register an arbitrarily large reservation set on each LR, - provided the reservation set includes all bytes of the addressed data word or - doubleword. - An SC can only pair with the most recent LR in program order. - An SC may succeed only if no store from another hart to the reservation set - can be observed to have occurred between the LR and the SC, - and if there is no other SC between the LR and itself in program order. - An SC may succeed only if no write from a device other than a hart to the bytes - accessed by the LR instruction can be observed to have occurred between the LR - and SC. - Note this LR might have had a different effective address and data size, - but reserved the SC's address as part of the reservation set. - - [NOTE] - ---- - Following this model, in systems with memory translation, an SC is allowed to succeed if the - earlier LR reserved the same location using an alias with a different virtual address, but is - also allowed to fail if the virtual address is different. - - To accommodate legacy devices and buses, writes from devices other than RISC-V harts are only - required to invalidate reservations when they overlap the bytes accessed by the LR. - These writes are not required to invalidate the reservation when they access other bytes in - the reservation set. - ---- - - The SC must fail if the address is not within the reservation set of the most - recent LR in program order. - The SC must fail if a store to the reservation set from another hart can be - observed to occur between the LR and SC. - The SC must fail if a write from some other device to the bytes accessed by the - LR can be observed to occur between the LR and SC. - (If such a device writes the reservation set but does not write the bytes accessed - by the LR, the SC may or may not fail.) - An SC must fail if there is another SC (to any address) between the LR and the SC - in program order. - The precise statement of the atomicity requirements for successful LR/SC sequences - is defined by the Atomicity Axiom of the memory model. - - [NOTE] - -- - The platform should provide a means to determine the size and shape of the reservation set. - - A platform specification may constrain the size and shape of the reservation set. - - A store-conditional instruction to a scratch word of memory should be used to forcibly invalidate any existing load reservation: - - * during a preemptive context switch, and - * if necessary when changing virtual to physical address mappings, such as when migrating pages that might contain an active reservation. - - The invalidation of a hart's reservation when it executes an LR or SC imply that a hart can only hold one reservation at a time, and that an SC can only pair with the most recent LR, and LR with the next following SC, in program order. This is a restriction to the Atomicity Axiom in Section 18.1 that ensures software runs correctly on expected common implementations that operate in this manner. - -- - - An SC instruction can never be observed by another RISC-V hart before the LR instruction that established the reservation. - - [NOTE] - -- - The LR/SC sequence can be given acquire semantics by setting the aq bit on the LR instruction. The LR/SC sequence can be given release semantics by by setting the rl bit on the SC instruction. Assuming suitable mappings for other atomic operations, setting the aq bit on the LR instruction, and setting the rl bit on the SC instruction makes the LR/SC sequence sequentially consistent in the C++ memory_order_seq_cst sense. Such a sequence does not act as a fence for ordering ordinary load and store instructions before and after the sequence. Specific instruction mappings for other C++ atomic operations, or stronger notions of "sequential consistency", may require both bits to be set on either or both of the LR or SC instruction. - - If neither bit is set on either LR or SC, the LR/SC sequence can be observed to occur before or after surrounding memory operations from the same RISC-V hart. This can be appropriate when the LR/SC sequence is used to implement a parallel reduction operation. - -- - - Software should not set the _rl_ bit on an LR instruction unless the _aq_ bit is also set. - LR.rl and SC.aq instructions are not guaranteed to provide any stronger ordering than those - with both bits clear, but may result in lower performance. - definedBy: - anyOf: [A, Zalrsc] - assembly: xd, xs2, xs1 - encoding: - match: 00011------------011-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); +$schema: "inst_schema.json#" +kind: instruction +name: sc.d +long_name: Store conditional doubleword +description: | + `sc.d` conditionally writes a doubleword in _rs2_ to the address in _rs1_: + the `sc.d` succeeds only if the reservation is still valid and the + reservation set contains the bytes being written. If the `sc.d` succeeds, + the instruction writes the doubleword in _rs2_ to memory, and it writes zero to _rd_. + If the `sc.d` fails, the instruction does not write to memory, and it writes a + nonzero value to _rd_. For the purposes of memory protection, a failed `sc.d` + may be treated like a store. Regardless of success or failure, executing an + `sc.d` instruction invalidates any reservation held by this hart. + + The failure code with value 1 encodes an unspecified failure. + Other failure codes are reserved at this time. + Portable software should only assume the failure code will be non-zero. + + The address held in _rs1_ must be naturally aligned to the size of the operand + (_i.e._, eight-byte aligned). + If the address is not naturally aligned, an address-misaligned exception or an + access-fault exception will be generated. + The access-fault exception can be generated for a memory access that would otherwise + be able to complete except for the misalignment, + if the misaligned access should not be emulated. + + [NOTE] + -- + Emulating misaligned LR/SC sequences is impractical in most systems. + + Misaligned LR/SC sequences also raise the possibility of accessing multiple + reservation sets at once, which present definitions do not provide for. + -- + + An implementation can register an arbitrarily large reservation set on each LR, + provided the reservation set includes all bytes of the addressed data word or + doubleword. + An SC can only pair with the most recent LR in program order. + An SC may succeed only if no store from another hart to the reservation set + can be observed to have occurred between the LR and the SC, + and if there is no other SC between the LR and itself in program order. + An SC may succeed only if no write from a device other than a hart to the bytes + accessed by the LR instruction can be observed to have occurred between the LR + and SC. + Note this LR might have had a different effective address and data size, + but reserved the SC's address as part of the reservation set. + + [NOTE] + ---- + Following this model, in systems with memory translation, an SC is allowed to succeed if the + earlier LR reserved the same location using an alias with a different virtual address, but is + also allowed to fail if the virtual address is different. + + To accommodate legacy devices and buses, writes from devices other than RISC-V harts are only + required to invalidate reservations when they overlap the bytes accessed by the LR. + These writes are not required to invalidate the reservation when they access other bytes in + the reservation set. + ---- + + The SC must fail if the address is not within the reservation set of the most + recent LR in program order. + The SC must fail if a store to the reservation set from another hart can be + observed to occur between the LR and SC. + The SC must fail if a write from some other device to the bytes accessed by the + LR can be observed to occur between the LR and SC. + (If such a device writes the reservation set but does not write the bytes accessed + by the LR, the SC may or may not fail.) + An SC must fail if there is another SC (to any address) between the LR and the SC + in program order. + The precise statement of the atomicity requirements for successful LR/SC sequences + is defined by the Atomicity Axiom of the memory model. + + [NOTE] + -- + The platform should provide a means to determine the size and shape of the reservation set. + + A platform specification may constrain the size and shape of the reservation set. + + A store-conditional instruction to a scratch word of memory should be used to forcibly invalidate any existing load reservation: + + * during a preemptive context switch, and + * if necessary when changing virtual to physical address mappings, such as when migrating pages that might contain an active reservation. + + The invalidation of a hart's reservation when it executes an LR or SC imply that a hart can only hold one reservation at a time, and that an SC can only pair with the most recent LR, and LR with the next following SC, in program order. This is a restriction to the Atomicity Axiom in Section 18.1 that ensures software runs correctly on expected common implementations that operate in this manner. + -- + + An SC instruction can never be observed by another RISC-V hart before the LR instruction that established the reservation. + + [NOTE] + -- + The LR/SC sequence can be given acquire semantics by setting the aq bit on the LR instruction. The LR/SC sequence can be given release semantics by by setting the rl bit on the SC instruction. Assuming suitable mappings for other atomic operations, setting the aq bit on the LR instruction, and setting the rl bit on the SC instruction makes the LR/SC sequence sequentially consistent in the C++ memory_order_seq_cst sense. Such a sequence does not act as a fence for ordering ordinary load and store instructions before and after the sequence. Specific instruction mappings for other C++ atomic operations, or stronger notions of "sequential consistency", may require both bits to be set on either or both of the LR or SC instruction. + + If neither bit is set on either LR or SC, the LR/SC sequence can be observed to occur before or after surrounding memory operations from the same RISC-V hart. This can be appropriate when the LR/SC sequence is used to implement a parallel reduction operation. + -- + + Software should not set the _rl_ bit on an LR instruction unless the _aq_ bit is also set. + LR.rl and SC.aq instructions are not guaranteed to provide any stronger ordering than those + with both bits clear, but may result in lower performance. +definedBy: + anyOf: [A, Zalrsc] +assembly: xd, xs2, xs1 +encoding: + match: 00011------------011-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1]; + XReg value = X[rs2]; + + if (!is_naturally_aligned<64>(virtual_address)) { + # can raise either LoadAddressMisaligned *or* LoadAccessFault + # + # from the spec: + # If the address is not naturally aligned, an address-misaligned exception or + # an access-fault exception will be generated. The access-fault exception can + # be generated for a memory access that would otherwise be able to complete except + # for the misalignment, if the misaligned access should not be emulated. + + if (LRSC_MISALIGNED_BEHAVIOR == "always raise misaligned exception") { + raise(ExceptionCode::LoadAddressMisaligned, effective_ldst_mode(), virtual_address); + } else if (LRSC_MISALIGNED_BEHAVIOR == "always raise access fault") { + raise(ExceptionCode::LoadAccessFault, effective_ldst_mode(), virtual_address); + } else { + unpredictable("Implementations may raise either a LoadAddressMisaligned or a LoadAccessFault when an LR/SC address is misaligned"); } + } - XReg virtual_address = X[rs1]; - XReg value = X[rs2]; - - if (!is_naturally_aligned<64>(virtual_address)) { - # can raise either LoadAddressMisaligned *or* LoadAccessFault - # - # from the spec: - # If the address is not naturally aligned, an address-misaligned exception or - # an access-fault exception will be generated. The access-fault exception can - # be generated for a memory access that would otherwise be able to complete except - # for the misalignment, if the misaligned access should not be emulated. - - if (LRSC_MISALIGNED_BEHAVIOR == "always raise misaligned exception") { - raise(ExceptionCode::LoadAddressMisaligned, effective_ldst_mode(), virtual_address); - } else if (LRSC_MISALIGNED_BEHAVIOR == "always raise access fault") { - raise(ExceptionCode::LoadAccessFault, effective_ldst_mode(), virtual_address); - } else { - unpredictable("Implementations may raise either a LoadAddressMisaligned or a LoadAccessFault when an LR/SC address is misaligned"); - } - } + Boolean success = store_conditional<64>(virtual_address, value, aq, rl, $encoding); + X[rd] = success ? 0 : 1; - Boolean success = store_conditional<64>(virtual_address, value, aq, rl, $encoding); - X[rd] = success ? 0 : 1; - - sail(): | - { - if speculate_conditional () == false then { - /* should only happen in rmem - * rmem: allow SC to fail very early +sail(): | + { + if speculate_conditional () == false then { + /* should only happen in rmem + * rmem: allow SC to fail very early + */ + X(rd) = zero_extend(0b1); RETIRE_SUCCESS + } else { + if extension("A") then { + /* normal non-rmem case + * rmem: SC is allowed to succeed (but might fail later) */ - X(rd) = zero_extend(0b1); RETIRE_SUCCESS - } else { - if extension("A") then { - /* normal non-rmem case - * rmem: SC is allowed to succeed (but might fail later) - */ - /* Get the address, X(rs1) (no offset). - * Extensions might perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), Write(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - let aligned : bool = - /* BYTE and HALF would only occur due to invalid decodes, but it doesn't hurt - * to treat them as valid here; otherwise we'd need to throw an internal_error. - */ - match width { - BYTE => true, - HALF => vaddr[0..0] == 0b0, - WORD => vaddr[1..0] == 0b00, - DOUBLE => vaddr[2..0] == 0b000 - }; - if not(aligned) - then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } - else { - if match_reservation(vaddr) == false then { - /* cannot happen in rmem */ - X(rd) = zero_extend(0b1); cancel_reservation(); RETIRE_SUCCESS - } else { - match translateAddr(vaddr, Write(Data)) { /* Write and ReadWrite are equivalent here: - * both result in a SAMO exception */ - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "STORECON expected word or double") - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - rs2_val = X(rs2); - let res : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, rs2_val[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, rs2_val[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, rs2_val[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, rs2_val, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "STORECON expected word or double") - }; - match (res) { - MemValue(true) => { X(rd) = zero_extend(0b0); cancel_reservation(); RETIRE_SUCCESS }, - MemValue(false) => { X(rd) = zero_extend(0b1); cancel_reservation(); RETIRE_SUCCESS }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + /* Get the address, X(rs1) (no offset). + * Extensions might perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), Write(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + let aligned : bool = + /* BYTE and HALF would only occur due to invalid decodes, but it doesn't hurt + * to treat them as valid here; otherwise we'd need to throw an internal_error. + */ + match width { + BYTE => true, + HALF => vaddr[0..0] == 0b0, + WORD => vaddr[1..0] == 0b00, + DOUBLE => vaddr[2..0] == 0b000 + }; + if not(aligned) + then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } + else { + if match_reservation(vaddr) == false then { + /* cannot happen in rmem */ + X(rd) = zero_extend(0b1); cancel_reservation(); RETIRE_SUCCESS + } else { + match translateAddr(vaddr, Write(Data)) { /* Write and ReadWrite are equivalent here: + * both result in a SAMO exception */ + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "STORECON expected word or double") + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + rs2_val = X(rs2); + let res : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, rs2_val[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, rs2_val[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, rs2_val[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, rs2_val, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "STORECON expected word or double") + }; + match (res) { + MemValue(true) => { X(rd) = zero_extend(0b0); cancel_reservation(); RETIRE_SUCCESS }, + MemValue(false) => { X(rd) = zero_extend(0b1); cancel_reservation(); RETIRE_SUCCESS }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -220,13 +221,14 @@ sc.d: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } } - - + } + + diff --git a/arch/inst/A/sc.w.yaml b/arch/inst/A/sc.w.yaml index efd798c94..c8dcac714 100644 --- a/arch/inst/A/sc.w.yaml +++ b/arch/inst/A/sc.w.yaml @@ -1,223 +1,224 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sc.w: - long_name: Store conditional word - description: | - `sc.w` conditionally writes a word in _rs2_ to the address in _rs1_: - the `sc.w` succeeds only if the reservation is still valid and the - reservation set contains the bytes being written. If the `sc.w` succeeds, - the instruction writes the word in _rs2_ to memory, and it writes zero to _rd_. - If the `sc.w` fails, the instruction does not write to memory, and it writes a - nonzero value to _rd_. For the purposes of memory protection, a failed `sc.w` - may be treated like a store. Regardless of success or failure, executing an - `sc.w` instruction invalidates any reservation held by this hart. - - <%- if XLEN == 64 -%> - [NOTE] - If a value other than 0 or 1 is defined as a result for `sc.w`, the value will before - sign-extended into _rd_. - <%- end -%> - - The failure code with value 1 encodes an unspecified failure. - Other failure codes are reserved at this time. - Portable software should only assume the failure code will be non-zero. - - The address held in _rs1_ must be naturally aligned to the size of the operand - (_i.e._, eight-byte aligned for doublewords and four-byte aligned for words). - If the address is not naturally aligned, an address-misaligned exception or an - access-fault exception will be generated. - The access-fault exception can be generated for a memory access that would otherwise - be able to complete except for the misalignment, - if the misaligned access should not be emulated. - - [NOTE] - -- - Emulating misaligned LR/SC sequences is impractical in most systems. - - Misaligned LR/SC sequences also raise the possibility of accessing multiple - reservation sets at once, which present definitions do not provide for. - -- - - An implementation can register an arbitrarily large reservation set on each LR, - provided the reservation set includes all bytes of the addressed data word or - doubleword. - An SC can only pair with the most recent LR in program order. - An SC may succeed only if no store from another hart to the reservation set - can be observed to have occurred between the LR and the SC, - and if there is no other SC between the LR and itself in program order. - An SC may succeed only if no write from a device other than a hart to the bytes - accessed by the LR instruction can be observed to have occurred between the LR - and SC. - Note this LR might have had a different effective address and data size, - but reserved the SC's address as part of the reservation set. - - [NOTE] - ---- - Following this model, in systems with memory translation, an SC is allowed to succeed if the - earlier LR reserved the same location using an alias with a different virtual address, but is - also allowed to fail if the virtual address is different. - - To accommodate legacy devices and buses, writes from devices other than RISC-V harts are only - required to invalidate reservations when they overlap the bytes accessed by the LR. - These writes are not required to invalidate the reservation when they access other bytes in - the reservation set. - ---- - - The SC must fail if the address is not within the reservation set of the most - recent LR in program order. - The SC must fail if a store to the reservation set from another hart can be - observed to occur between the LR and SC. - The SC must fail if a write from some other device to the bytes accessed by the - LR can be observed to occur between the LR and SC. - (If such a device writes the reservation set but does not write the bytes accessed - by the LR, the SC may or may not fail.) - An SC must fail if there is another SC (to any address) between the LR and the SC - in program order. - The precise statement of the atomicity requirements for successful LR/SC sequences - is defined by the Atomicity Axiom of the memory model. - - [NOTE] - -- - The platform should provide a means to determine the size and shape of the reservation set. - - A platform specification may constrain the size and shape of the reservation set. - - A store-conditional instruction to a scratch word of memory should be used to forcibly invalidate any existing load reservation: - - * during a preemptive context switch, and - * if necessary when changing virtual to physical address mappings, such as when migrating pages that might contain an active reservation. - - The invalidation of a hart's reservation when it executes an LR or SC imply that a hart can only hold one reservation at a time, and that an SC can only pair with the most recent LR, and LR with the next following SC, in program order. This is a restriction to the Atomicity Axiom in Section 18.1 that ensures software runs correctly on expected common implementations that operate in this manner. - -- - - An SC instruction can never be observed by another RISC-V hart before the LR instruction that established the reservation. - - [NOTE] - -- - The LR/SC sequence can be given acquire semantics by setting the aq bit on the LR instruction. The LR/SC sequence can be given release semantics by by setting the rl bit on the SC instruction. Assuming suitable mappings for other atomic operations, setting the aq bit on the LR instruction, and setting the rl bit on the SC instruction makes the LR/SC sequence sequentially consistent in the C++ memory_order_seq_cst sense. Such a sequence does not act as a fence for ordering ordinary load and store instructions before and after the sequence. Specific instruction mappings for other C++ atomic operations, or stronger notions of "sequential consistency", may require both bits to be set on either or both of the LR or SC instruction. - - If neither bit is set on either LR or SC, the LR/SC sequence can be observed to occur before or after surrounding memory operations from the same RISC-V hart. This can be appropriate when the LR/SC sequence is used to implement a parallel reduction operation. - -- - - Software should not set the _rl_ bit on an LR instruction unless the _aq_ bit is also set. - LR.rl and SC.aq instructions are not guaranteed to provide any stronger ordering than those - with both bits clear, but may result in lower performance. - definedBy: - anyOf: [A, Zalrsc] - assembly: xd, xs2, xs1 - encoding: - match: 00011------------010-----0101111 - variables: - - name: aq - location: 26 - - name: rl - location: 25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); +$schema: "inst_schema.json#" +kind: instruction +name: sc.w +long_name: Store conditional word +description: | + `sc.w` conditionally writes a word in _rs2_ to the address in _rs1_: + the `sc.w` succeeds only if the reservation is still valid and the + reservation set contains the bytes being written. If the `sc.w` succeeds, + the instruction writes the word in _rs2_ to memory, and it writes zero to _rd_. + If the `sc.w` fails, the instruction does not write to memory, and it writes a + nonzero value to _rd_. For the purposes of memory protection, a failed `sc.w` + may be treated like a store. Regardless of success or failure, executing an + `sc.w` instruction invalidates any reservation held by this hart. + + <%- if XLEN == 64 -%> + [NOTE] + If a value other than 0 or 1 is defined as a result for `sc.w`, the value will before + sign-extended into _rd_. + <%- end -%> + + The failure code with value 1 encodes an unspecified failure. + Other failure codes are reserved at this time. + Portable software should only assume the failure code will be non-zero. + + The address held in _rs1_ must be naturally aligned to the size of the operand + (_i.e._, eight-byte aligned for doublewords and four-byte aligned for words). + If the address is not naturally aligned, an address-misaligned exception or an + access-fault exception will be generated. + The access-fault exception can be generated for a memory access that would otherwise + be able to complete except for the misalignment, + if the misaligned access should not be emulated. + + [NOTE] + -- + Emulating misaligned LR/SC sequences is impractical in most systems. + + Misaligned LR/SC sequences also raise the possibility of accessing multiple + reservation sets at once, which present definitions do not provide for. + -- + + An implementation can register an arbitrarily large reservation set on each LR, + provided the reservation set includes all bytes of the addressed data word or + doubleword. + An SC can only pair with the most recent LR in program order. + An SC may succeed only if no store from another hart to the reservation set + can be observed to have occurred between the LR and the SC, + and if there is no other SC between the LR and itself in program order. + An SC may succeed only if no write from a device other than a hart to the bytes + accessed by the LR instruction can be observed to have occurred between the LR + and SC. + Note this LR might have had a different effective address and data size, + but reserved the SC's address as part of the reservation set. + + [NOTE] + ---- + Following this model, in systems with memory translation, an SC is allowed to succeed if the + earlier LR reserved the same location using an alias with a different virtual address, but is + also allowed to fail if the virtual address is different. + + To accommodate legacy devices and buses, writes from devices other than RISC-V harts are only + required to invalidate reservations when they overlap the bytes accessed by the LR. + These writes are not required to invalidate the reservation when they access other bytes in + the reservation set. + ---- + + The SC must fail if the address is not within the reservation set of the most + recent LR in program order. + The SC must fail if a store to the reservation set from another hart can be + observed to occur between the LR and SC. + The SC must fail if a write from some other device to the bytes accessed by the + LR can be observed to occur between the LR and SC. + (If such a device writes the reservation set but does not write the bytes accessed + by the LR, the SC may or may not fail.) + An SC must fail if there is another SC (to any address) between the LR and the SC + in program order. + The precise statement of the atomicity requirements for successful LR/SC sequences + is defined by the Atomicity Axiom of the memory model. + + [NOTE] + -- + The platform should provide a means to determine the size and shape of the reservation set. + + A platform specification may constrain the size and shape of the reservation set. + + A store-conditional instruction to a scratch word of memory should be used to forcibly invalidate any existing load reservation: + + * during a preemptive context switch, and + * if necessary when changing virtual to physical address mappings, such as when migrating pages that might contain an active reservation. + + The invalidation of a hart's reservation when it executes an LR or SC imply that a hart can only hold one reservation at a time, and that an SC can only pair with the most recent LR, and LR with the next following SC, in program order. This is a restriction to the Atomicity Axiom in Section 18.1 that ensures software runs correctly on expected common implementations that operate in this manner. + -- + + An SC instruction can never be observed by another RISC-V hart before the LR instruction that established the reservation. + + [NOTE] + -- + The LR/SC sequence can be given acquire semantics by setting the aq bit on the LR instruction. The LR/SC sequence can be given release semantics by by setting the rl bit on the SC instruction. Assuming suitable mappings for other atomic operations, setting the aq bit on the LR instruction, and setting the rl bit on the SC instruction makes the LR/SC sequence sequentially consistent in the C++ memory_order_seq_cst sense. Such a sequence does not act as a fence for ordering ordinary load and store instructions before and after the sequence. Specific instruction mappings for other C++ atomic operations, or stronger notions of "sequential consistency", may require both bits to be set on either or both of the LR or SC instruction. + + If neither bit is set on either LR or SC, the LR/SC sequence can be observed to occur before or after surrounding memory operations from the same RISC-V hart. This can be appropriate when the LR/SC sequence is used to implement a parallel reduction operation. + -- + + Software should not set the _rl_ bit on an LR instruction unless the _aq_ bit is also set. + LR.rl and SC.aq instructions are not guaranteed to provide any stronger ordering than those + with both bits clear, but may result in lower performance. +definedBy: + anyOf: [A, Zalrsc] +assembly: xd, xs2, xs1 +encoding: + match: 00011------------010-----0101111 + variables: + - name: aq + location: 26 + - name: rl + location: 25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { + # even though this is a memory operation, the exception occurs before that would be known, + # so mode() is the correct reporting mode rathat than effective_ldst_mode() + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1]; + XReg value = X[rs2]; + + if (!is_naturally_aligned<32>(virtual_address)) { + # can raise either LoadAddressMisaligned *or* LoadAccessFault + # + # from the spec: + # If the address is not naturally aligned, an address-misaligned exception or + # an access-fault exception will be generated. The access-fault exception can + # be generated for a memory access that would otherwise be able to complete except + # for the misalignment, if the misaligned access should not be emulated. + + if (LRSC_MISALIGNED_BEHAVIOR == "always raise misaligned exception") { + raise(ExceptionCode::LoadAddressMisaligned, effective_ldst_mode(), virtual_address); + } else if (LRSC_MISALIGNED_BEHAVIOR == "always raise access fault") { + raise(ExceptionCode::LoadAccessFault, effective_ldst_mode(), virtual_address); + } else { + unpredictable("Implementations may raise either a LoadAddressMisaligned or a LoadAccessFault when an LR/SC address is misaligned"); } + } - XReg virtual_address = X[rs1]; - XReg value = X[rs2]; - - if (!is_naturally_aligned<32>(virtual_address)) { - # can raise either LoadAddressMisaligned *or* LoadAccessFault - # - # from the spec: - # If the address is not naturally aligned, an address-misaligned exception or - # an access-fault exception will be generated. The access-fault exception can - # be generated for a memory access that would otherwise be able to complete except - # for the misalignment, if the misaligned access should not be emulated. - - if (LRSC_MISALIGNED_BEHAVIOR == "always raise misaligned exception") { - raise(ExceptionCode::LoadAddressMisaligned, effective_ldst_mode(), virtual_address); - } else if (LRSC_MISALIGNED_BEHAVIOR == "always raise access fault") { - raise(ExceptionCode::LoadAccessFault, effective_ldst_mode(), virtual_address); - } else { - unpredictable("Implementations may raise either a LoadAddressMisaligned or a LoadAccessFault when an LR/SC address is misaligned"); - } - } + Boolean success = store_conditional<32>(virtual_address, value, aq, rl, $encoding); + X[rd] = success ? 0 : 1; - Boolean success = store_conditional<32>(virtual_address, value, aq, rl, $encoding); - X[rd] = success ? 0 : 1; - - sail(): | - { - if speculate_conditional () == false then { - /* should only happen in rmem - * rmem: allow SC to fail very early +sail(): | + { + if speculate_conditional () == false then { + /* should only happen in rmem + * rmem: allow SC to fail very early + */ + X(rd) = zero_extend(0b1); RETIRE_SUCCESS + } else { + if extension("A") then { + /* normal non-rmem case + * rmem: SC is allowed to succeed (but might fail later) */ - X(rd) = zero_extend(0b1); RETIRE_SUCCESS - } else { - if extension("A") then { - /* normal non-rmem case - * rmem: SC is allowed to succeed (but might fail later) - */ - /* Get the address, X(rs1) (no offset). - * Extensions might perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), Write(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - let aligned : bool = - /* BYTE and HALF would only occur due to invalid decodes, but it doesn't hurt - * to treat them as valid here; otherwise we'd need to throw an internal_error. - */ - match width { - BYTE => true, - HALF => vaddr[0..0] == 0b0, - WORD => vaddr[1..0] == 0b00, - DOUBLE => vaddr[2..0] == 0b000 - }; - if not(aligned) - then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } - else { - if match_reservation(vaddr) == false then { - /* cannot happen in rmem */ - X(rd) = zero_extend(0b1); cancel_reservation(); RETIRE_SUCCESS - } else { - match translateAddr(vaddr, Write(Data)) { /* Write and ReadWrite are equivalent here: - * both result in a SAMO exception */ - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "STORECON expected word or double") - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - rs2_val = X(rs2); - let res : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, rs2_val[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, rs2_val[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, rs2_val[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, rs2_val, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "STORECON expected word or double") - }; - match (res) { - MemValue(true) => { X(rd) = zero_extend(0b0); cancel_reservation(); RETIRE_SUCCESS }, - MemValue(false) => { X(rd) = zero_extend(0b1); cancel_reservation(); RETIRE_SUCCESS }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + /* Get the address, X(rs1) (no offset). + * Extensions might perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), Write(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + let aligned : bool = + /* BYTE and HALF would only occur due to invalid decodes, but it doesn't hurt + * to treat them as valid here; otherwise we'd need to throw an internal_error. + */ + match width { + BYTE => true, + HALF => vaddr[0..0] == 0b0, + WORD => vaddr[1..0] == 0b00, + DOUBLE => vaddr[2..0] == 0b000 + }; + if not(aligned) + then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } + else { + if match_reservation(vaddr) == false then { + /* cannot happen in rmem */ + X(rd) = zero_extend(0b1); cancel_reservation(); RETIRE_SUCCESS + } else { + match translateAddr(vaddr, Write(Data)) { /* Write and ReadWrite are equivalent here: + * both result in a SAMO exception */ + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "STORECON expected word or double") + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + rs2_val = X(rs2); + let res : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, rs2_val[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, rs2_val[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, rs2_val[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, rs2_val, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "STORECON expected word or double") + }; + match (res) { + MemValue(true) => { X(rd) = zero_extend(0b0); cancel_reservation(); RETIRE_SUCCESS }, + MemValue(false) => { X(rd) = zero_extend(0b1); cancel_reservation(); RETIRE_SUCCESS }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -226,13 +227,14 @@ sc.w: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } } - - + } + + diff --git a/arch/inst/B/add.uw.yaml b/arch/inst/B/add.uw.yaml index 305153b64..c07907206 100644 --- a/arch/inst/B/add.uw.yaml +++ b/arch/inst/B/add.uw.yaml @@ -1,55 +1,57 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -add.uw: - long_name: Add unsigned word - base: 64 - description: | - This instruction performs an XLEN-wide addition between rs2 and the - zero-extended least-significant word of rs1. - definedBy: - anyOf: [B, Zba] - assembly: xd, xs1, xs2 - encoding: - match: 0000100----------000-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - pseudoinstructions: - - when: rs2 == 0 - to: zext.w xd, xs1 - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = X[rs2] + X[rs1][31:0]; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let shamt : bits(2) = match op { - RISCV_ADDUW => 0b00, - RISCV_SH1ADDUW => 0b01, - RISCV_SH2ADDUW => 0b10, - RISCV_SH3ADDUW => 0b11 - }; - let result : xlenbits = (zero_extend(rs1_val[31..0]) << shamt) + rs2_val; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: add.uw +long_name: Add unsigned word +base: 64 +description: | + This instruction performs an XLEN-wide addition between rs2 and the + zero-extended least-significant word of rs1. +definedBy: + anyOf: [B, Zba] +assembly: xd, xs1, xs2 +encoding: + match: 0000100----------000-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +pseudoinstructions: +- when: rs2 == 0 + to: zext.w xd, xs1 +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = X[rs2] + X[rs1][31:0]; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let shamt : bits(2) = match op { + RISCV_ADDUW => 0b00, + RISCV_SH1ADDUW => 0b01, + RISCV_SH2ADDUW => 0b10, + RISCV_SH3ADDUW => 0b11 + }; + let result : xlenbits = (zero_extend(rs1_val[31..0]) << shamt) + rs2_val; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/andn.yaml b/arch/inst/B/andn.yaml index a09ed482e..9de7b36a2 100644 --- a/arch/inst/B/andn.yaml +++ b/arch/inst/B/andn.yaml @@ -1,60 +1,62 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -andn: - long_name: AND with inverted operand - description: | - This instruction performs the bitwise logical AND operation between `rs1` and the - bitwise inversion of `rs2`. - definedBy: - anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] - assembly: xd, xs1, xs2 - encoding: - match: 0100000----------111-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = X[rs2] & ~X[rs1]; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ANDN => rs1_val & ~(rs2_val), - RISCV_ORN => rs1_val | ~(rs2_val), - RISCV_XNOR => ~(rs1_val ^ rs2_val), - RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), - RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), - RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_ROL => if sizeof(xlen) == 32 - then rs1_val <<< rs2_val[4..0] - else rs1_val <<< rs2_val[5..0], - RISCV_ROR => if sizeof(xlen) == 32 - then rs1_val >>> rs2_val[4..0] - else rs1_val >>> rs2_val[5..0] - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: andn +long_name: AND with inverted operand +description: | + This instruction performs the bitwise logical AND operation between `rs1` and the + bitwise inversion of `rs2`. +definedBy: + anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] +assembly: xd, xs1, xs2 +encoding: + match: 0100000----------111-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = X[rs2] & ~X[rs1]; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ANDN => rs1_val & ~(rs2_val), + RISCV_ORN => rs1_val | ~(rs2_val), + RISCV_XNOR => ~(rs1_val ^ rs2_val), + RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), + RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), + RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_ROL => if sizeof(xlen) == 32 + then rs1_val <<< rs2_val[4..0] + else rs1_val <<< rs2_val[5..0], + RISCV_ROR => if sizeof(xlen) == 32 + then rs1_val >>> rs2_val[4..0] + else rs1_val >>> rs2_val[5..0] + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/bclr.yaml b/arch/inst/B/bclr.yaml index 57c8e6b9d..b6b8117f7 100644 --- a/arch/inst/B/bclr.yaml +++ b/arch/inst/B/bclr.yaml @@ -1,54 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -bclr: - long_name: Single-Bit clear (Register) - description: | - This instruction returns rs1 with a single bit cleared at the index specified in rs2. - The index is read from the lower log2(XLEN) bits of rs2. - definedBy: - anyOf: [B, Zbs] - assembly: xd, xs1, xs2 - encoding: - match: 0100100----------001-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg index = X[rs2] & (xlen() - 1); - X[rd] = X[rs1] & ~(1 << index); - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let mask : xlenbits = if sizeof(xlen) == 32 - then zero_extend(0b1) << rs2_val[4..0] - else zero_extend(0b1) << rs2_val[5..0]; - let result : xlenbits = match op { - RISCV_BCLR => rs1_val & ~(mask), - RISCV_BEXT => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), - RISCV_BINV => rs1_val ^ mask, - RISCV_BSET => rs1_val | mask - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: bclr +long_name: Single-Bit clear (Register) +description: | + This instruction returns rs1 with a single bit cleared at the index specified in rs2. + The index is read from the lower log2(XLEN) bits of rs2. +definedBy: + anyOf: [B, Zbs] +assembly: xd, xs1, xs2 +encoding: + match: 0100100----------001-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg index = X[rs2] & (xlen() - 1); + X[rd] = X[rs1] & ~(1 << index); + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let mask : xlenbits = if sizeof(xlen) == 32 + then zero_extend(0b1) << rs2_val[4..0] + else zero_extend(0b1) << rs2_val[5..0]; + let result : xlenbits = match op { + RISCV_BCLR => rs1_val & ~(mask), + RISCV_BEXT => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), + RISCV_BINV => rs1_val ^ mask, + RISCV_BSET => rs1_val | mask + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/bclri.yaml b/arch/inst/B/bclri.yaml index b776689cc..c718e3cf5 100644 --- a/arch/inst/B/bclri.yaml +++ b/arch/inst/B/bclri.yaml @@ -1,64 +1,66 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -bclri: - long_name: Single-Bit clear (Immediate) - description: | - This instruction returns rs1 with a single bit cleared at the index specified in shamt. The - index is read from the lower log2(XLEN) bits of shamt. For RV32, the encodings corresponding - to shamt[5]=1 are reserved. - definedBy: - anyOf: [B, Zbs] - assembly: xd, xs1, shamt - encoding: - RV32: - match: 0100100----------001-----0010011 - variables: - - name: shamt - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - RV64: - match: 010010-----------001-----0010011 - variables: - - name: shamt - location: 25-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: bclri +long_name: Single-Bit clear (Immediate) +description: | + This instruction returns rs1 with a single bit cleared at the index specified in shamt. The + index is read from the lower log2(XLEN) bits of shamt. For RV32, the encodings corresponding + to shamt[5]=1 are reserved. +definedBy: + anyOf: [B, Zbs] +assembly: xd, xs1, shamt +encoding: + RV32: + match: 0100100----------001-----0010011 + variables: + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 + RV64: + match: 010010-----------001-----0010011 + variables: + - name: shamt + location: 25-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg index = shamt & (xlen() - 1); - X[rd] = X[rs1] & ~(1 << index); + XReg index = shamt & (xlen() - 1); + X[rd] = X[rs1] & ~(1 << index); - sail(): | - { - let rs1_val = X(rs1); - let mask : xlenbits = if sizeof(xlen) == 32 - then zero_extend(0b1) << shamt[4..0] - else zero_extend(0b1) << shamt; - let result : xlenbits = match op { - RISCV_BCLRI => rs1_val & ~(mask), - RISCV_BEXTI => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), - RISCV_BINVI => rs1_val ^ mask, - RISCV_BSETI => rs1_val | mask - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +sail(): | + { + let rs1_val = X(rs1); + let mask : xlenbits = if sizeof(xlen) == 32 + then zero_extend(0b1) << shamt[4..0] + else zero_extend(0b1) << shamt; + let result : xlenbits = match op { + RISCV_BCLRI => rs1_val & ~(mask), + RISCV_BEXTI => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), + RISCV_BINVI => rs1_val ^ mask, + RISCV_BSETI => rs1_val | mask + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/bext.yaml b/arch/inst/B/bext.yaml index bd14665ea..4d3b4caf7 100644 --- a/arch/inst/B/bext.yaml +++ b/arch/inst/B/bext.yaml @@ -1,54 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -bext: - long_name: Single-Bit extract (Register) - description: | - This instruction returns a single bit extracted from rs1 at the index specified in rs2. - The index is read from the lower log2(XLEN) bits of rs2. - definedBy: - anyOf: [B, Zbs] - assembly: xd, xs1, xs2 - encoding: - match: 0100100----------101-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg index = X[rs2] & (xlen() - 1); - X[rd] = (X[rs1] >> index) & 1; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let mask : xlenbits = if sizeof(xlen) == 32 - then zero_extend(0b1) << rs2_val[4..0] - else zero_extend(0b1) << rs2_val[5..0]; - let result : xlenbits = match op { - RISCV_BCLR => rs1_val & ~(mask), - RISCV_BEXT => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), - RISCV_BINV => rs1_val ^ mask, - RISCV_BSET => rs1_val | mask - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: bext +long_name: Single-Bit extract (Register) +description: | + This instruction returns a single bit extracted from rs1 at the index specified in rs2. + The index is read from the lower log2(XLEN) bits of rs2. +definedBy: + anyOf: [B, Zbs] +assembly: xd, xs1, xs2 +encoding: + match: 0100100----------101-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg index = X[rs2] & (xlen() - 1); + X[rd] = (X[rs1] >> index) & 1; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let mask : xlenbits = if sizeof(xlen) == 32 + then zero_extend(0b1) << rs2_val[4..0] + else zero_extend(0b1) << rs2_val[5..0]; + let result : xlenbits = match op { + RISCV_BCLR => rs1_val & ~(mask), + RISCV_BEXT => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), + RISCV_BINV => rs1_val ^ mask, + RISCV_BSET => rs1_val | mask + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/bexti.yaml b/arch/inst/B/bexti.yaml index fff79a4d0..fbb2705c5 100644 --- a/arch/inst/B/bexti.yaml +++ b/arch/inst/B/bexti.yaml @@ -1,64 +1,66 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -bexti: - long_name: Single-Bit extract (Immediate) - description: | - This instruction returns a single bit extracted from rs1 at the index specified in rs2. - The index is read from the lower log2(XLEN) bits of shamt. For RV32, the encodings - corresponding to shamt[5]=1 are reserved. - definedBy: - anyOf: [B, Zbs] - assembly: xd, xs1, shamt - encoding: - RV32: - match: 0100100----------101-----0010011 - variables: - - name: shamt - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - RV64: - match: 010010-----------101-----0010011 - variables: - - name: shamt - location: 25-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: bexti +long_name: Single-Bit extract (Immediate) +description: | + This instruction returns a single bit extracted from rs1 at the index specified in rs2. + The index is read from the lower log2(XLEN) bits of shamt. For RV32, the encodings + corresponding to shamt[5]=1 are reserved. +definedBy: + anyOf: [B, Zbs] +assembly: xd, xs1, shamt +encoding: + RV32: + match: 0100100----------101-----0010011 + variables: + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 + RV64: + match: 010010-----------101-----0010011 + variables: + - name: shamt + location: 25-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg index = shamt & (xlen() - 1); - X[rd] = (X[rs1] >> index) & 1; + XReg index = shamt & (xlen() - 1); + X[rd] = (X[rs1] >> index) & 1; - sail(): | - { - let rs1_val = X(rs1); - let mask : xlenbits = if sizeof(xlen) == 32 - then zero_extend(0b1) << shamt[4..0] - else zero_extend(0b1) << shamt; - let result : xlenbits = match op { - RISCV_BCLRI => rs1_val & ~(mask), - RISCV_BEXTI => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), - RISCV_BINVI => rs1_val ^ mask, - RISCV_BSETI => rs1_val | mask - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +sail(): | + { + let rs1_val = X(rs1); + let mask : xlenbits = if sizeof(xlen) == 32 + then zero_extend(0b1) << shamt[4..0] + else zero_extend(0b1) << shamt; + let result : xlenbits = match op { + RISCV_BCLRI => rs1_val & ~(mask), + RISCV_BEXTI => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), + RISCV_BINVI => rs1_val ^ mask, + RISCV_BSETI => rs1_val | mask + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/binv.yaml b/arch/inst/B/binv.yaml index 45d4d59e0..8390947af 100644 --- a/arch/inst/B/binv.yaml +++ b/arch/inst/B/binv.yaml @@ -1,54 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -binv: - long_name: Single-Bit invert (Register) - description: | - This instruction returns rs1 with a single bit inverted at the index specified in rs2. - The index is read from the lower log2(XLEN) bits of rs2. - definedBy: - anyOf: [B, Zbs] - assembly: xd, xs1, xs2 - encoding: - match: 0110100----------001-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg index = X[rs2] & (xlen() - 1); - X[rd] = X[rs1] ^ (1 << index); - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let mask : xlenbits = if sizeof(xlen) == 32 - then zero_extend(0b1) << rs2_val[4..0] - else zero_extend(0b1) << rs2_val[5..0]; - let result : xlenbits = match op { - RISCV_BCLR => rs1_val & ~(mask), - RISCV_BEXT => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), - RISCV_BINV => rs1_val ^ mask, - RISCV_BSET => rs1_val | mask - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: binv +long_name: Single-Bit invert (Register) +description: | + This instruction returns rs1 with a single bit inverted at the index specified in rs2. + The index is read from the lower log2(XLEN) bits of rs2. +definedBy: + anyOf: [B, Zbs] +assembly: xd, xs1, xs2 +encoding: + match: 0110100----------001-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg index = X[rs2] & (xlen() - 1); + X[rd] = X[rs1] ^ (1 << index); + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let mask : xlenbits = if sizeof(xlen) == 32 + then zero_extend(0b1) << rs2_val[4..0] + else zero_extend(0b1) << rs2_val[5..0]; + let result : xlenbits = match op { + RISCV_BCLR => rs1_val & ~(mask), + RISCV_BEXT => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), + RISCV_BINV => rs1_val ^ mask, + RISCV_BSET => rs1_val | mask + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/binvi.yaml b/arch/inst/B/binvi.yaml index 4c9c5bb07..cd9be980b 100644 --- a/arch/inst/B/binvi.yaml +++ b/arch/inst/B/binvi.yaml @@ -1,64 +1,66 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -binvi: - long_name: Single-Bit invert (Immediate) - description: | - This instruction returns rs1 with a single bit inverted at the index specified in shamt. - The index is read from the lower log2(XLEN) bits of shamt. - For RV32, the encodings corresponding to shamt[5]=1 are reserved. - definedBy: - anyOf: [B, Zbs] - assembly: xd, xs1, shamt - encoding: - RV32: - match: 0110100----------001-----0010011 - variables: - - name: shamt - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - RV64: - match: 011010-----------001-----0010011 - variables: - - name: shamt - location: 25-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: binvi +long_name: Single-Bit invert (Immediate) +description: | + This instruction returns rs1 with a single bit inverted at the index specified in shamt. + The index is read from the lower log2(XLEN) bits of shamt. + For RV32, the encodings corresponding to shamt[5]=1 are reserved. +definedBy: + anyOf: [B, Zbs] +assembly: xd, xs1, shamt +encoding: + RV32: + match: 0110100----------001-----0010011 + variables: + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 + RV64: + match: 011010-----------001-----0010011 + variables: + - name: shamt + location: 25-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg index = shamt & (xlen() - 1); - X[rd] = X[rs1] ^ (1 << index); + XReg index = shamt & (xlen() - 1); + X[rd] = X[rs1] ^ (1 << index); - sail(): | - { - let rs1_val = X(rs1); - let mask : xlenbits = if sizeof(xlen) == 32 - then zero_extend(0b1) << shamt[4..0] - else zero_extend(0b1) << shamt; - let result : xlenbits = match op { - RISCV_BCLRI => rs1_val & ~(mask), - RISCV_BEXTI => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), - RISCV_BINVI => rs1_val ^ mask, - RISCV_BSETI => rs1_val | mask - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +sail(): | + { + let rs1_val = X(rs1); + let mask : xlenbits = if sizeof(xlen) == 32 + then zero_extend(0b1) << shamt[4..0] + else zero_extend(0b1) << shamt; + let result : xlenbits = match op { + RISCV_BCLRI => rs1_val & ~(mask), + RISCV_BEXTI => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), + RISCV_BINVI => rs1_val ^ mask, + RISCV_BSETI => rs1_val | mask + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/bset.yaml b/arch/inst/B/bset.yaml index 072b8605e..5cf11e49f 100644 --- a/arch/inst/B/bset.yaml +++ b/arch/inst/B/bset.yaml @@ -1,54 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -bset: - long_name: Single-Bit set (Register) - description: | - This instruction returns rs1 with a single bit set at the index specified in rs2. - The index is read from the lower log2(XLEN) bits of rs2. - definedBy: - anyOf: [B, Zbs] - assembly: xd, xs1, xs2 - encoding: - match: 0010100----------001-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg index = X[rs2] & (xlen() - 1); - X[rd] = X[rs1] | (1 << index); - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let mask : xlenbits = if sizeof(xlen) == 32 - then zero_extend(0b1) << rs2_val[4..0] - else zero_extend(0b1) << rs2_val[5..0]; - let result : xlenbits = match op { - RISCV_BCLR => rs1_val & ~(mask), - RISCV_BEXT => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), - RISCV_BINV => rs1_val ^ mask, - RISCV_BSET => rs1_val | mask - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: bset +long_name: Single-Bit set (Register) +description: | + This instruction returns rs1 with a single bit set at the index specified in rs2. + The index is read from the lower log2(XLEN) bits of rs2. +definedBy: + anyOf: [B, Zbs] +assembly: xd, xs1, xs2 +encoding: + match: 0010100----------001-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg index = X[rs2] & (xlen() - 1); + X[rd] = X[rs1] | (1 << index); + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let mask : xlenbits = if sizeof(xlen) == 32 + then zero_extend(0b1) << rs2_val[4..0] + else zero_extend(0b1) << rs2_val[5..0]; + let result : xlenbits = match op { + RISCV_BCLR => rs1_val & ~(mask), + RISCV_BEXT => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), + RISCV_BINV => rs1_val ^ mask, + RISCV_BSET => rs1_val | mask + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/bseti.yaml b/arch/inst/B/bseti.yaml index f938dcb42..84466cdde 100644 --- a/arch/inst/B/bseti.yaml +++ b/arch/inst/B/bseti.yaml @@ -1,64 +1,66 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -bseti: - long_name: Single-Bit set (Immediate) - description: | - This instruction returns rs1 with a single bit set at the index specified in shamt. - The index is read from the lower log2(XLEN) bits of shamt. - For RV32, the encodings corresponding to shamt[5]=1 are reserved. - definedBy: - anyOf: [B, Zbs] - assembly: xd, xs1, shamt - encoding: - RV32: - match: 0010100----------001-----0010011 - variables: - - name: shamt - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - RV64: - match: 001010-----------001-----0010011 - variables: - - name: shamt - location: 25-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: bseti +long_name: Single-Bit set (Immediate) +description: | + This instruction returns rs1 with a single bit set at the index specified in shamt. + The index is read from the lower log2(XLEN) bits of shamt. + For RV32, the encodings corresponding to shamt[5]=1 are reserved. +definedBy: + anyOf: [B, Zbs] +assembly: xd, xs1, shamt +encoding: + RV32: + match: 0010100----------001-----0010011 + variables: + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 + RV64: + match: 001010-----------001-----0010011 + variables: + - name: shamt + location: 25-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg index = shamt & (xlen() - 1); - X[rd] = X[rs1] | (1 << index); + XReg index = shamt & (xlen() - 1); + X[rd] = X[rs1] | (1 << index); - sail(): | - { - let rs1_val = X(rs1); - let mask : xlenbits = if sizeof(xlen) == 32 - then zero_extend(0b1) << shamt[4..0] - else zero_extend(0b1) << shamt; - let result : xlenbits = match op { - RISCV_BCLRI => rs1_val & ~(mask), - RISCV_BEXTI => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), - RISCV_BINVI => rs1_val ^ mask, - RISCV_BSETI => rs1_val | mask - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +sail(): | + { + let rs1_val = X(rs1); + let mask : xlenbits = if sizeof(xlen) == 32 + then zero_extend(0b1) << shamt[4..0] + else zero_extend(0b1) << shamt; + let result : xlenbits = match op { + RISCV_BCLRI => rs1_val & ~(mask), + RISCV_BEXTI => zero_extend(bool_to_bits((rs1_val & mask) != zeros())), + RISCV_BINVI => rs1_val ^ mask, + RISCV_BSETI => rs1_val | mask + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/clmul.yaml b/arch/inst/B/clmul.yaml index f9394291e..42c104025 100644 --- a/arch/inst/B/clmul.yaml +++ b/arch/inst/B/clmul.yaml @@ -1,57 +1,59 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -clmul: - long_name: Carry-less multiply (low-part) - description: | - `clmul` produces the lower half of the 2*XLEN carry-less product - definedBy: - anyOf: [B, Zbc, Zbkc, Zk, Zkn, Zks] - assembly: xd, xs1, xs2 - encoding: - match: 0000101----------001-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg rs1_val = X[rs1]; - XReg rs2_val = X[rs2]; - XReg output = 0; - - for (U32 i=0; i < xlen(); i++) { - output = (((rs2_val >> i) & 1) == 1) - ? output ^ (rs1_val << i) - : output; - } - - X[rd] = output; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - result : xlenbits = zeros(); - foreach (i from 0 to (xlen_val - 1)) - if rs2_val[i] == bitone then result = result ^ (rs1_val << i); - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: clmul +long_name: Carry-less multiply (low-part) +description: | + `clmul` produces the lower half of the 2*XLEN carry-less product +definedBy: + anyOf: [B, Zbc, Zbkc, Zk, Zkn, Zks] +assembly: xd, xs1, xs2 +encoding: + match: 0000101----------001-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg rs1_val = X[rs1]; + XReg rs2_val = X[rs2]; + XReg output = 0; + + for (U32 i=0; i < xlen(); i++) { + output = (((rs2_val >> i) & 1) == 1) + ? output ^ (rs1_val << i) + : output; + } + + X[rd] = output; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + result : xlenbits = zeros(); + foreach (i from 0 to (xlen_val - 1)) + if rs2_val[i] == bitone then result = result ^ (rs1_val << i); + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/clmulh.yaml b/arch/inst/B/clmulh.yaml index ee6cdb74a..d93284718 100644 --- a/arch/inst/B/clmulh.yaml +++ b/arch/inst/B/clmulh.yaml @@ -1,57 +1,59 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -clmulh: - long_name: Carry-less multiply (high-part) - description: | - `clmulh` produces the upper half of the 2*XLEN carry-less product - definedBy: - anyOf: [B, Zbc, Zbkc, Zk, Zkn, Zks] - assembly: xd, xs1, xs2 - encoding: - match: 0000101----------011-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg rs1_val = X[rs1]; - XReg rs2_val = X[rs2]; - XReg output = 0; - - for (U32 i=1; i <= xlen(); i++) { - output = (((rs2_val >> i) & 1) == 1) - ? output ^ (rs1_val >> (xlen() - i)) - : output; - } - - X[rd] = output; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - result : xlenbits = zeros(); - foreach (i from 0 to (xlen_val - 1)) - if rs2_val[i] == bitone then result = result ^ (rs1_val >> (xlen_val - i)); - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: clmulh +long_name: Carry-less multiply (high-part) +description: | + `clmulh` produces the upper half of the 2*XLEN carry-less product +definedBy: + anyOf: [B, Zbc, Zbkc, Zk, Zkn, Zks] +assembly: xd, xs1, xs2 +encoding: + match: 0000101----------011-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg rs1_val = X[rs1]; + XReg rs2_val = X[rs2]; + XReg output = 0; + + for (U32 i=1; i <= xlen(); i++) { + output = (((rs2_val >> i) & 1) == 1) + ? output ^ (rs1_val >> (xlen() - i)) + : output; + } + + X[rd] = output; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + result : xlenbits = zeros(); + foreach (i from 0 to (xlen_val - 1)) + if rs2_val[i] == bitone then result = result ^ (rs1_val >> (xlen_val - i)); + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/clmulr.yaml b/arch/inst/B/clmulr.yaml index 03c632d05..249382ceb 100644 --- a/arch/inst/B/clmulr.yaml +++ b/arch/inst/B/clmulr.yaml @@ -1,56 +1,58 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -clmulr: - long_name: Carry-less multiply (reversed) - description: | - `clmulr` produces bits 2*XLEN-2:XLEN-1 of the 2*XLEN carry-less product - definedBy: - anyOf: [B, Zbc] - assembly: xd, xs1, xs2 - access: - s: always - u: always - vs: always - vu: always - encoding: - match: 0000101----------010-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg rs1_val = X[rs1]; - XReg rs2_val = X[rs2]; - XReg output = 0; - - for (U32 i=0; i < xlen(); i++) { - output = (((rs2_val >> i) & 1) == 1) - ? output ^ (rs1_val >> (xlen() - i - 1)) - : output; - } - - X[rd] = output; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - result : xlenbits = zeros(); - foreach (i from 0 to (xlen_val - 1)) - if rs2_val[i] == bitone then result = result ^ (rs1_val >> (xlen_val - i - 1)); - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: clmulr +long_name: Carry-less multiply (reversed) +description: | + `clmulr` produces bits 2*XLEN-2:XLEN-1 of the 2*XLEN carry-less product +definedBy: + anyOf: [B, Zbc] +assembly: xd, xs1, xs2 +access: + s: always + u: always + vs: always + vu: always +encoding: + match: 0000101----------010-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg rs1_val = X[rs1]; + XReg rs2_val = X[rs2]; + XReg output = 0; + + for (U32 i=0; i < xlen(); i++) { + output = (((rs2_val >> i) & 1) == 1) + ? output ^ (rs1_val >> (xlen() - i - 1)) + : output; + } + + X[rd] = output; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + result : xlenbits = zeros(); + foreach (i from 0 to (xlen_val - 1)) + if rs2_val[i] == bitone then result = result ^ (rs1_val >> (xlen_val - i - 1)); + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/clz.yaml b/arch/inst/B/clz.yaml index 506895312..f17057957 100644 --- a/arch/inst/B/clz.yaml +++ b/arch/inst/B/clz.yaml @@ -1,49 +1,51 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -clz: - long_name: Count leading zero bits - description: | - This instruction counts the number of 0's before the first 1, - starting at the most-significant bit (i.e., XLEN-1) and progressing to bit 0. - Accordingly, if the input is 0, the output is XLEN, and if the most-significant - bit of the input is a 1, the output is 0. - definedBy: - anyOf: [B, Zbb] - assembly: xd, xs1 - encoding: - match: 011000000000-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = (xlen() - 1) - $signed(highest_set_bit(X[rs1])); - - - - sail(): | - { - let rs1_val = X(rs1); - result : nat = 0; - done : bool = false; - foreach (i from (sizeof(xlen) - 1) downto 0) - if not(done) then if rs1_val[i] == bitzero - then result = result + 1 - else done = true; - X(rd) = to_bits(sizeof(xlen), result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: clz +long_name: Count leading zero bits +description: | + This instruction counts the number of 0's before the first 1, + starting at the most-significant bit (i.e., XLEN-1) and progressing to bit 0. + Accordingly, if the input is 0, the output is XLEN, and if the most-significant + bit of the input is a 1, the output is 0. +definedBy: + anyOf: [B, Zbb] +assembly: xd, xs1 +encoding: + match: 011000000000-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = (xlen() - 1) - $signed(highest_set_bit(X[rs1])); + + + +sail(): | + { + let rs1_val = X(rs1); + result : nat = 0; + done : bool = false; + foreach (i from (sizeof(xlen) - 1) downto 0) + if not(done) then if rs1_val[i] == bitzero + then result = result + 1 + else done = true; + X(rd) = to_bits(sizeof(xlen), result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/clzw.yaml b/arch/inst/B/clzw.yaml index dd945ad17..7c5b6224a 100644 --- a/arch/inst/B/clzw.yaml +++ b/arch/inst/B/clzw.yaml @@ -1,49 +1,51 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -clzw: - long_name: Count leading zero bits in word - description: | - This instruction counts the number of 0's before the first 1 starting at bit 31 and progressing to bit 0. - Accordingly, if the least-significant word is 0, the output is 32, and if the most-significant - bit of the word (_i.e._, bit 31) is a 1, the output is 0. - base: 64 - definedBy: - anyOf: [B, Zbb] - assembly: xd, xs1 - encoding: - match: 011000000000-----001-----0011011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = 31 - $signed(highest_set_bit(X[rs1][31:0])); - - - - sail(): | - { - let rs1_val = X(rs1); - result : nat = 0; - done : bool = false; - foreach (i from 31 downto 0) - if not(done) then if rs1_val[i] == bitzero - then result = result + 1 - else done = true; - X(rd) = to_bits(sizeof(xlen), result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: clzw +long_name: Count leading zero bits in word +description: | + This instruction counts the number of 0's before the first 1 starting at bit 31 and progressing to bit 0. + Accordingly, if the least-significant word is 0, the output is 32, and if the most-significant + bit of the word (_i.e._, bit 31) is a 1, the output is 0. +base: 64 +definedBy: + anyOf: [B, Zbb] +assembly: xd, xs1 +encoding: + match: 011000000000-----001-----0011011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = 31 - $signed(highest_set_bit(X[rs1][31:0])); + + + +sail(): | + { + let rs1_val = X(rs1); + result : nat = 0; + done : bool = false; + foreach (i from 31 downto 0) + if not(done) then if rs1_val[i] == bitzero + then result = result + 1 + else done = true; + X(rd) = to_bits(sizeof(xlen), result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/cpop.yaml b/arch/inst/B/cpop.yaml index 74951f0f3..a09524600 100644 --- a/arch/inst/B/cpop.yaml +++ b/arch/inst/B/cpop.yaml @@ -1,64 +1,66 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -cpop: - long_name: Count set bits - description: | - This instructions counts the number of 1's (i.e., set bits) in the source register. +$schema: "inst_schema.json#" +kind: instruction +name: cpop +long_name: Count set bits +description: | + This instructions counts the number of 1's (i.e., set bits) in the source register. - .Software Hint - [NOTE] - ---- - This operations is known as population count, popcount, sideways sum, - bit summation, or Hamming weight. + .Software Hint + [NOTE] + ---- + This operations is known as population count, popcount, sideways sum, + bit summation, or Hamming weight. - The GCC builtin function `__builtin_popcount (unsigned int x)` is - implemented by cpop on RV32 and by cpopw on RV64. The GCC builtin - function `__builtin_popcountl (unsigned long x)` for LP64 is - implemented by cpop on RV64. - ---- - definedBy: - anyOf: [B, Zbb] - assembly: xd, xs1 - encoding: - match: 011000000010-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + The GCC builtin function `__builtin_popcount (unsigned int x)` is + implemented by cpop on RV32 and by cpopw on RV64. The GCC builtin + function `__builtin_popcountl (unsigned long x)` for LP64 is + implemented by cpop on RV64. + ---- +definedBy: + anyOf: [B, Zbb] +assembly: xd, xs1 +encoding: + match: 011000000010-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg bitcount = 0; - XReg rs1_val = X[rs1]; + XReg bitcount = 0; + XReg rs1_val = X[rs1]; - for (U32 i=0; i < xlen(); i++) { - if (rs1_val[i] == 1'b1) { - bitcount = bitcount + 1; - } + for (U32 i=0; i < xlen(); i++) { + if (rs1_val[i] == 1'b1) { + bitcount = bitcount + 1; } + } - X[rd] = bitcount; + X[rd] = bitcount; - sail(): | - { - let rs1_val = X(rs1); - result : nat = 0; - foreach (i from 0 to (xlen_val - 1)) - if rs1_val[i] == bitone then result = result + 1; - X(rd) = to_bits(sizeof(xlen), result); - RETIRE_SUCCESS - } - - +sail(): | + { + let rs1_val = X(rs1); + result : nat = 0; + foreach (i from 0 to (xlen_val - 1)) + if rs1_val[i] == bitone then result = result + 1; + X(rd) = to_bits(sizeof(xlen), result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/cpopw.yaml b/arch/inst/B/cpopw.yaml index 5a75bfdf5..59e65f41d 100644 --- a/arch/inst/B/cpopw.yaml +++ b/arch/inst/B/cpopw.yaml @@ -1,65 +1,67 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -cpopw: - long_name: Count set bits in word - description: | - This instructions counts the number of 1's (i.e., set bits) in the least-significant word of the source egister. +$schema: "inst_schema.json#" +kind: instruction +name: cpopw +long_name: Count set bits in word +description: | + This instructions counts the number of 1's (i.e., set bits) in the least-significant word of the source egister. - .Software Hint - [NOTE] - ---- - This operations is known as population count, popcount, sideways sum, - bit summation, or Hamming weight. + .Software Hint + [NOTE] + ---- + This operations is known as population count, popcount, sideways sum, + bit summation, or Hamming weight. - The GCC builtin function `__builtin_popcount (unsigned int x)` is - implemented by cpop on RV32 and by cpopw on RV64. The GCC builtin - function `__builtin_popcountl (unsigned long x)` for LP64 is - implemented by cpop on RV64. - ---- - definedBy: - anyOf: [B, Zbb] - base: 64 - assembly: xd, xs1 - encoding: - match: 011000000010-----001-----0011011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + The GCC builtin function `__builtin_popcount (unsigned int x)` is + implemented by cpop on RV32 and by cpopw on RV64. The GCC builtin + function `__builtin_popcountl (unsigned long x)` for LP64 is + implemented by cpop on RV64. + ---- +definedBy: + anyOf: [B, Zbb] +base: 64 +assembly: xd, xs1 +encoding: + match: 011000000010-----001-----0011011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg bitcount = 0; - XReg rs1_val = X[rs1]; + XReg bitcount = 0; + XReg rs1_val = X[rs1]; - for (U32 i=0; i < 32; i++) { - if (rs1_val[i] == 1'b1) { - bitcount = bitcount + 1; - } + for (U32 i=0; i < 32; i++) { + if (rs1_val[i] == 1'b1) { + bitcount = bitcount + 1; } + } - X[rd] = bitcount; + X[rd] = bitcount; - sail(): | - { - let rs1_val = X(rs1); - result : nat = 0; - foreach (i from 0 to 31) - if rs1_val[i] == bitone then result = result + 1; - X(rd) = to_bits(sizeof(xlen), result); - RETIRE_SUCCESS - } - - +sail(): | + { + let rs1_val = X(rs1); + result : nat = 0; + foreach (i from 0 to 31) + if rs1_val[i] == bitone then result = result + 1; + X(rd) = to_bits(sizeof(xlen), result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/ctz.yaml b/arch/inst/B/ctz.yaml index fcd2e296e..848c32352 100644 --- a/arch/inst/B/ctz.yaml +++ b/arch/inst/B/ctz.yaml @@ -1,50 +1,52 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -ctz: - long_name: Count trailing zero bits - description: | - This instruction counts the number of 0's before the first 1, - starting at the least-significant bit (i.e., 0) and progressing - to the most-significant bit (i.e., XLEN-1). Accordingly, if the - input is 0, the output is XLEN, and if the least-significant bit - of the input is a 1, the output is 0. - definedBy: - anyOf: [B, Zbb] - assembly: xd, xs1 - encoding: - match: 011000000001-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = (xlen() - 1) - $signed(lowest_set_bit(X[rs1])); - - - - sail(): | - { - let rs1_val = X(rs1); - result : nat = 0; - done : bool = false; - foreach (i from 0 to (sizeof(xlen) - 1)) - if not(done) then if rs1_val[i] == bitzero - then result = result + 1 - else done = true; - X(rd) = to_bits(sizeof(xlen), result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: ctz +long_name: Count trailing zero bits +description: | + This instruction counts the number of 0's before the first 1, + starting at the least-significant bit (i.e., 0) and progressing + to the most-significant bit (i.e., XLEN-1). Accordingly, if the + input is 0, the output is XLEN, and if the least-significant bit + of the input is a 1, the output is 0. +definedBy: + anyOf: [B, Zbb] +assembly: xd, xs1 +encoding: + match: 011000000001-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = (xlen() - 1) - $signed(lowest_set_bit(X[rs1])); + + + +sail(): | + { + let rs1_val = X(rs1); + result : nat = 0; + done : bool = false; + foreach (i from 0 to (sizeof(xlen) - 1)) + if not(done) then if rs1_val[i] == bitzero + then result = result + 1 + else done = true; + X(rd) = to_bits(sizeof(xlen), result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/ctzw.yaml b/arch/inst/B/ctzw.yaml index 88bc86bb1..1ef098151 100644 --- a/arch/inst/B/ctzw.yaml +++ b/arch/inst/B/ctzw.yaml @@ -1,51 +1,53 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -ctzw: - long_name: Count trailing zero bits in word - description: | - This instruction counts the number of 0's before the first 1, - starting at the least-significant bit (i.e., 0) and progressing - to the most-significant bit of the least-significant word (i.e., 31). Accordingly, if the - least-significant word is 0, the output is 32, and if the least-significant bit - of the input is a 1, the output is 0. - definedBy: - anyOf: [B, Zbb] - base: 64 - assembly: xd, xs1 - encoding: - match: 011000000001-----001-----0011011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = (xlen() - 1) - $signed(lowest_set_bit(X[rs1][31:0])); - - - - sail(): | - { - let rs1_val = X(rs1); - result : nat = 0; - done : bool = false; - foreach (i from 0 to 31) - if not(done) then if rs1_val[i] == bitzero - then result = result + 1 - else done = true; - X(rd) = to_bits(sizeof(xlen), result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: ctzw +long_name: Count trailing zero bits in word +description: | + This instruction counts the number of 0's before the first 1, + starting at the least-significant bit (i.e., 0) and progressing + to the most-significant bit of the least-significant word (i.e., 31). Accordingly, if the + least-significant word is 0, the output is 32, and if the least-significant bit + of the input is a 1, the output is 0. +definedBy: + anyOf: [B, Zbb] +base: 64 +assembly: xd, xs1 +encoding: + match: 011000000001-----001-----0011011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = (xlen() - 1) - $signed(lowest_set_bit(X[rs1][31:0])); + + + +sail(): | + { + let rs1_val = X(rs1); + result : nat = 0; + done : bool = false; + foreach (i from 0 to 31) + if not(done) then if rs1_val[i] == bitzero + then result = result + 1 + else done = true; + X(rd) = to_bits(sizeof(xlen), result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/max.yaml b/arch/inst/B/max.yaml index 5256e0c0b..a612ff282 100644 --- a/arch/inst/B/max.yaml +++ b/arch/inst/B/max.yaml @@ -1,66 +1,68 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -max: - long_name: Maximum - description: | - This instruction returns the larger of two signed integers. +$schema: "inst_schema.json#" +kind: instruction +name: max +long_name: Maximum +description: | + This instruction returns the larger of two signed integers. - .Software Hint - [NOTE] - Calculating the absolute value of a signed integer can be performed using the - following sequence: `neg rD,rS` followed by `max rD,rS,rD. When using this - common sequence, it is suggested that they are scheduled with no intervening - instructions so that implementations that are so optimized can fuse them - together. - definedBy: - anyOf: [B, Zbb] - assembly: xd, xs1, xs2 - encoding: - match: 0000101----------110-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + .Software Hint + [NOTE] + Calculating the absolute value of a signed integer can be performed using the + following sequence: `neg rD,rS` followed by `max rD,rS,rD. When using this + common sequence, it is suggested that they are scheduled with no intervening + instructions so that implementations that are so optimized can fuse them + together. +definedBy: + anyOf: [B, Zbb] +assembly: xd, xs1, xs2 +encoding: + match: 0000101----------110-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - X[rd] = ($signed(X[rs1]) > $signed(X[rs2])) ? X[rs1] : X[rs2]; + X[rd] = ($signed(X[rs1]) > $signed(X[rs2])) ? X[rs1] : X[rs2]; - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ANDN => rs1_val & ~(rs2_val), - RISCV_ORN => rs1_val | ~(rs2_val), - RISCV_XNOR => ~(rs1_val ^ rs2_val), - RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), - RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), - RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_ROL => if sizeof(xlen) == 32 - then rs1_val <<< rs2_val[4..0] - else rs1_val <<< rs2_val[5..0], - RISCV_ROR => if sizeof(xlen) == 32 - then rs1_val >>> rs2_val[4..0] - else rs1_val >>> rs2_val[5..0] - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ANDN => rs1_val & ~(rs2_val), + RISCV_ORN => rs1_val | ~(rs2_val), + RISCV_XNOR => ~(rs1_val ^ rs2_val), + RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), + RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), + RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_ROL => if sizeof(xlen) == 32 + then rs1_val <<< rs2_val[4..0] + else rs1_val <<< rs2_val[5..0], + RISCV_ROR => if sizeof(xlen) == 32 + then rs1_val >>> rs2_val[4..0] + else rs1_val >>> rs2_val[5..0] + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/maxu.yaml b/arch/inst/B/maxu.yaml index ea196055d..bc8e60282 100644 --- a/arch/inst/B/maxu.yaml +++ b/arch/inst/B/maxu.yaml @@ -1,58 +1,60 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -maxu: - long_name: Unsigned maximum - description: | - This instruction returns the larger of two unsigned integers. - definedBy: - anyOf: [B, Zbb] - assembly: xd, xs1, xs2 - encoding: - match: 0000101----------111-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = (X[rs1] > X[rs2]) ? X[rs1] : X[rs2]; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ANDN => rs1_val & ~(rs2_val), - RISCV_ORN => rs1_val | ~(rs2_val), - RISCV_XNOR => ~(rs1_val ^ rs2_val), - RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), - RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), - RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_ROL => if sizeof(xlen) == 32 - then rs1_val <<< rs2_val[4..0] - else rs1_val <<< rs2_val[5..0], - RISCV_ROR => if sizeof(xlen) == 32 - then rs1_val >>> rs2_val[4..0] - else rs1_val >>> rs2_val[5..0] - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: maxu +long_name: Unsigned maximum +description: | + This instruction returns the larger of two unsigned integers. +definedBy: + anyOf: [B, Zbb] +assembly: xd, xs1, xs2 +encoding: + match: 0000101----------111-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = (X[rs1] > X[rs2]) ? X[rs1] : X[rs2]; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ANDN => rs1_val & ~(rs2_val), + RISCV_ORN => rs1_val | ~(rs2_val), + RISCV_XNOR => ~(rs1_val ^ rs2_val), + RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), + RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), + RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_ROL => if sizeof(xlen) == 32 + then rs1_val <<< rs2_val[4..0] + else rs1_val <<< rs2_val[5..0], + RISCV_ROR => if sizeof(xlen) == 32 + then rs1_val >>> rs2_val[4..0] + else rs1_val >>> rs2_val[5..0] + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/min.yaml b/arch/inst/B/min.yaml index 4161ddfdc..073572963 100644 --- a/arch/inst/B/min.yaml +++ b/arch/inst/B/min.yaml @@ -1,58 +1,60 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -min: - long_name: Minimum - description: | - This instruction returns the smaller of two signed integers. - definedBy: - anyOf: [B, Zbb] - assembly: xd, xs1, xs2 - encoding: - match: 0000101----------100-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = ($signed(X[rs1]) < $signed(X[rs2])) ? X[rs1] : X[rs2]; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ANDN => rs1_val & ~(rs2_val), - RISCV_ORN => rs1_val | ~(rs2_val), - RISCV_XNOR => ~(rs1_val ^ rs2_val), - RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), - RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), - RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_ROL => if sizeof(xlen) == 32 - then rs1_val <<< rs2_val[4..0] - else rs1_val <<< rs2_val[5..0], - RISCV_ROR => if sizeof(xlen) == 32 - then rs1_val >>> rs2_val[4..0] - else rs1_val >>> rs2_val[5..0] - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: min +long_name: Minimum +description: | + This instruction returns the smaller of two signed integers. +definedBy: + anyOf: [B, Zbb] +assembly: xd, xs1, xs2 +encoding: + match: 0000101----------100-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = ($signed(X[rs1]) < $signed(X[rs2])) ? X[rs1] : X[rs2]; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ANDN => rs1_val & ~(rs2_val), + RISCV_ORN => rs1_val | ~(rs2_val), + RISCV_XNOR => ~(rs1_val ^ rs2_val), + RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), + RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), + RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_ROL => if sizeof(xlen) == 32 + then rs1_val <<< rs2_val[4..0] + else rs1_val <<< rs2_val[5..0], + RISCV_ROR => if sizeof(xlen) == 32 + then rs1_val >>> rs2_val[4..0] + else rs1_val >>> rs2_val[5..0] + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/minu.yaml b/arch/inst/B/minu.yaml index dfe214bd5..1d4966312 100644 --- a/arch/inst/B/minu.yaml +++ b/arch/inst/B/minu.yaml @@ -1,58 +1,60 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -minu: - long_name: Unsigned minumum - description: | - This instruction returns the smaller of two unsigned integers. - definedBy: - anyOf: [B, Zbb] - assembly: xd, xs1, xs2 - encoding: - match: 0000101----------101-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = (X[rs1] < X[rs2]) ? X[rs1] : X[rs2]; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ANDN => rs1_val & ~(rs2_val), - RISCV_ORN => rs1_val | ~(rs2_val), - RISCV_XNOR => ~(rs1_val ^ rs2_val), - RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), - RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), - RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_ROL => if sizeof(xlen) == 32 - then rs1_val <<< rs2_val[4..0] - else rs1_val <<< rs2_val[5..0], - RISCV_ROR => if sizeof(xlen) == 32 - then rs1_val >>> rs2_val[4..0] - else rs1_val >>> rs2_val[5..0] - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: minu +long_name: Unsigned minumum +description: | + This instruction returns the smaller of two unsigned integers. +definedBy: + anyOf: [B, Zbb] +assembly: xd, xs1, xs2 +encoding: + match: 0000101----------101-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = (X[rs1] < X[rs2]) ? X[rs1] : X[rs2]; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ANDN => rs1_val & ~(rs2_val), + RISCV_ORN => rs1_val | ~(rs2_val), + RISCV_XNOR => ~(rs1_val ^ rs2_val), + RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), + RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), + RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_ROL => if sizeof(xlen) == 32 + then rs1_val <<< rs2_val[4..0] + else rs1_val <<< rs2_val[5..0], + RISCV_ROR => if sizeof(xlen) == 32 + then rs1_val >>> rs2_val[4..0] + else rs1_val >>> rs2_val[5..0] + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/orc.b.yaml b/arch/inst/B/orc.b.yaml index 195af23b1..ccb867b57 100644 --- a/arch/inst/B/orc.b.yaml +++ b/arch/inst/B/orc.b.yaml @@ -1,54 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -orc.b: - long_name: Bitware OR-combine, byte granule - description: | - Combines the bits within each byte using bitwise logical OR. This sets the bits - of each byte in the result rd to all zeros if no bit within the respective byte - of rs is set, or to all ones if any bit within the respective byte of rs is set. - definedBy: - anyOf: [B, Zbb] - assembly: xd, xs1, xs2 - encoding: - match: 001010000111-----101-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg input = X[rs1]; - XReg output = 0; - - for (U32 i=0; i<(xlen() - 8); i = i+8) { - output[(i+7):i] = (input[(i+7):i] == 0) ? 8'd0 : ~8'd0; - } - - X[rd] = output; - - - - sail(): | - { - let rs1_val = X(rs1); - result : xlenbits = zeros(); - foreach (i from 0 to (sizeof(xlen) - 8) by 8) - result[(i + 7) .. i] = if rs1_val[(i + 7) .. i] == zeros() - then 0x00 - else 0xFF; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: orc.b +long_name: Bitware OR-combine, byte granule +description: | + Combines the bits within each byte using bitwise logical OR. This sets the bits + of each byte in the result rd to all zeros if no bit within the respective byte + of rs is set, or to all ones if any bit within the respective byte of rs is set. +definedBy: + anyOf: [B, Zbb] +assembly: xd, xs1, xs2 +encoding: + match: 001010000111-----101-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg input = X[rs1]; + XReg output = 0; + + for (U32 i=0; i<(xlen() - 8); i = i+8) { + output[(i+7):i] = (input[(i+7):i] == 0) ? 8'd0 : ~8'd0; + } + + X[rd] = output; + + + +sail(): | + { + let rs1_val = X(rs1); + result : xlenbits = zeros(); + foreach (i from 0 to (sizeof(xlen) - 8) by 8) + result[(i + 7) .. i] = if rs1_val[(i + 7) .. i] == zeros() + then 0x00 + else 0xFF; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/orn.yaml b/arch/inst/B/orn.yaml index a54ae78c4..ba06cea15 100644 --- a/arch/inst/B/orn.yaml +++ b/arch/inst/B/orn.yaml @@ -1,59 +1,61 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -orn: - long_name: OR with inverted operand - description: | - This instruction performs the bitwise logical OR operation between rs1 and the bitwise inversion of rs2. - definedBy: - anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] - assembly: xd, xs1, xs2 - encoding: - match: 0100000----------110-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = X[rs1] | ~X[rs2]; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ANDN => rs1_val & ~(rs2_val), - RISCV_ORN => rs1_val | ~(rs2_val), - RISCV_XNOR => ~(rs1_val ^ rs2_val), - RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), - RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), - RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_ROL => if sizeof(xlen) == 32 - then rs1_val <<< rs2_val[4..0] - else rs1_val <<< rs2_val[5..0], - RISCV_ROR => if sizeof(xlen) == 32 - then rs1_val >>> rs2_val[4..0] - else rs1_val >>> rs2_val[5..0] - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: orn +long_name: OR with inverted operand +description: | + This instruction performs the bitwise logical OR operation between rs1 and the bitwise inversion of rs2. +definedBy: + anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] +assembly: xd, xs1, xs2 +encoding: + match: 0100000----------110-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = X[rs1] | ~X[rs2]; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ANDN => rs1_val & ~(rs2_val), + RISCV_ORN => rs1_val | ~(rs2_val), + RISCV_XNOR => ~(rs1_val ^ rs2_val), + RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), + RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), + RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_ROL => if sizeof(xlen) == 32 + then rs1_val <<< rs2_val[4..0] + else rs1_val <<< rs2_val[5..0], + RISCV_ROR => if sizeof(xlen) == 32 + then rs1_val >>> rs2_val[4..0] + else rs1_val >>> rs2_val[5..0] + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/rev8.yaml b/arch/inst/B/rev8.yaml index 34b61ec3c..d2e50680a 100644 --- a/arch/inst/B/rev8.yaml +++ b/arch/inst/B/rev8.yaml @@ -1,70 +1,72 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -rev8: - long_name: Byte-reverse register (RV64 encoding) - description: | - This instruction reverses the order of the bytes in rs1. +$schema: "inst_schema.json#" +kind: instruction +name: rev8 +long_name: Byte-reverse register (RV64 encoding) +description: | + This instruction reverses the order of the bytes in rs1. - [NOTE] - The rev8 mnemonic corresponds to different instruction encodings in RV32 and RV64. + [NOTE] + The rev8 mnemonic corresponds to different instruction encodings in RV32 and RV64. - [NOTE] - The byte-reverse operation is only available for the full register width. To emulate word-sized - and halfword-sized byte-reversal, perform a `rev8 rd,rs` followed by a `srai rd,rd,K`, where K - is XLEN-32 and XLEN-16, respectively. - definedBy: - anyOf: [B, Zbb, Zbkb] - assembly: xd, xs1 - encoding: - RV32: - match: 011010011000-----101-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - RV64: - match: 011010111000-----101-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + [NOTE] + The byte-reverse operation is only available for the full register width. To emulate word-sized + and halfword-sized byte-reversal, perform a `rev8 rd,rs` followed by a `srai rd,rd,K`, where K + is XLEN-32 and XLEN-16, respectively. +definedBy: + anyOf: [B, Zbb, Zbkb] +assembly: xd, xs1 +encoding: + RV32: + match: 011010011000-----101-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 + RV64: + match: 011010111000-----101-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg input = X[rs1]; - XReg output = 0; + XReg input = X[rs1]; + XReg output = 0; - XReg j = xlen() - 1; + XReg j = xlen() - 1; - for (U32 i=0; i<(xlen()-8); i = i+8) { - output[(i+7):i] = input[j:(j-7)]; - j = j - 8; - } + for (U32 i=0; i<(xlen()-8); i = i+8) { + output[(i+7):i] = input[j:(j-7)]; + j = j - 8; + } - X[rd] = output; + X[rd] = output; - sail(): | - { - let rs1_val = X(rs1); - result : xlenbits = zeros(); - foreach (i from 0 to (sizeof(xlen) - 8) by 8) - result[(i + 7) .. i] = rs1_val[(sizeof(xlen) - i - 1) .. (sizeof(xlen) - i - 8)]; - X(rd) = result; - RETIRE_SUCCESS - } - - +sail(): | + { + let rs1_val = X(rs1); + result : xlenbits = zeros(); + foreach (i from 0 to (sizeof(xlen) - 8) by 8) + result[(i + 7) .. i] = rs1_val[(sizeof(xlen) - i - 1) .. (sizeof(xlen) - i - 8)]; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/rol.yaml b/arch/inst/B/rol.yaml index 298719f15..f65cf35fa 100644 --- a/arch/inst/B/rol.yaml +++ b/arch/inst/B/rol.yaml @@ -1,61 +1,63 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -rol: - long_name: Rotate left (Register) - description: | - This instruction performs a rotate left of rs1 by the amount in least-significant `log2(XLEN)` bits of rs2. - definedBy: - anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] - assembly: xd, xs1, xs2 - encoding: - match: 0110000----------001-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg shamt = (xlen() == 32) ? X[rs2][4:0] : X[rs2][5:0]; - - X[rd] = (X[rs1] << shamt) | (X[rs1] >> (xlen() - shamt)); - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ANDN => rs1_val & ~(rs2_val), - RISCV_ORN => rs1_val | ~(rs2_val), - RISCV_XNOR => ~(rs1_val ^ rs2_val), - RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), - RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), - RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_ROL => if sizeof(xlen) == 32 - then rs1_val <<< rs2_val[4..0] - else rs1_val <<< rs2_val[5..0], - RISCV_ROR => if sizeof(xlen) == 32 - then rs1_val >>> rs2_val[4..0] - else rs1_val >>> rs2_val[5..0] - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: rol +long_name: Rotate left (Register) +description: | + This instruction performs a rotate left of rs1 by the amount in least-significant `log2(XLEN)` bits of rs2. +definedBy: + anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] +assembly: xd, xs1, xs2 +encoding: + match: 0110000----------001-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg shamt = (xlen() == 32) ? X[rs2][4:0] : X[rs2][5:0]; + + X[rd] = (X[rs1] << shamt) | (X[rs1] >> (xlen() - shamt)); + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ANDN => rs1_val & ~(rs2_val), + RISCV_ORN => rs1_val | ~(rs2_val), + RISCV_XNOR => ~(rs1_val ^ rs2_val), + RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), + RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), + RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_ROL => if sizeof(xlen) == 32 + then rs1_val <<< rs2_val[4..0] + else rs1_val <<< rs2_val[5..0], + RISCV_ROR => if sizeof(xlen) == 32 + then rs1_val >>> rs2_val[4..0] + else rs1_val >>> rs2_val[5..0] + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/rolw.yaml b/arch/inst/B/rolw.yaml index 0a3d0e9bc..105f568ba 100644 --- a/arch/inst/B/rolw.yaml +++ b/arch/inst/B/rolw.yaml @@ -1,55 +1,57 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -rolw: - long_name: Rotate left word (Register) - description: | - This instruction performs a rotate left of the least-significant word of rs1 by the amount in least-significant 5 bits of rs2. - The resulting word value is sign-extended by copying bit 31 to all of the more-significant bits. - definedBy: - anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] - assembly: xd, xs1, xs2 - base: 64 - encoding: - match: 0110000----------001-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg rs1_word = X[rs1][31:0]; - XReg shamt = X[rs2][4:0]; - - XReg unextended_result = (rs1_word << shamt) | (rs1_word >> (32 - shamt)); - - X[rd] = {{32{unextended_result[31]}}, unextended_result}; - - - - sail(): | - { - let rs1_val = (X(rs1))[31..0]; - let shamt = (X(rs2))[4..0]; - let result : bits(32) = match op { - RISCV_ROLW => rs1_val <<< shamt, - RISCV_RORW => rs1_val >>> shamt - }; - X(rd) = sign_extend(result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: rolw +long_name: Rotate left word (Register) +description: | + This instruction performs a rotate left of the least-significant word of rs1 by the amount in least-significant 5 bits of rs2. + The resulting word value is sign-extended by copying bit 31 to all of the more-significant bits. +definedBy: + anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] +assembly: xd, xs1, xs2 +base: 64 +encoding: + match: 0110000----------001-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg rs1_word = X[rs1][31:0]; + XReg shamt = X[rs2][4:0]; + + XReg unextended_result = (rs1_word << shamt) | (rs1_word >> (32 - shamt)); + + X[rd] = {{32{unextended_result[31]}}, unextended_result}; + + + +sail(): | + { + let rs1_val = (X(rs1))[31..0]; + let shamt = (X(rs2))[4..0]; + let result : bits(32) = match op { + RISCV_ROLW => rs1_val <<< shamt, + RISCV_RORW => rs1_val >>> shamt + }; + X(rd) = sign_extend(result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/ror.yaml b/arch/inst/B/ror.yaml index 522571edf..a7be3ba46 100644 --- a/arch/inst/B/ror.yaml +++ b/arch/inst/B/ror.yaml @@ -1,61 +1,63 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -ror: - long_name: Rotate right (Register) - description: | - This instruction performs a rotate right of rs1 by the amount in least-significant `log2(XLEN)` bits of rs2. - definedBy: - anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] - assembly: xd, xs1, xs2 - encoding: - match: 0110000----------101-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg shamt = (xlen() == 32) ? X[rs2][4:0] : X[rs2][5:0]; - - X[rd] = (X[rs1] >> shamt) | (X[rs1] << (xlen() - shamt)); - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ANDN => rs1_val & ~(rs2_val), - RISCV_ORN => rs1_val | ~(rs2_val), - RISCV_XNOR => ~(rs1_val ^ rs2_val), - RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), - RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), - RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_ROL => if sizeof(xlen) == 32 - then rs1_val <<< rs2_val[4..0] - else rs1_val <<< rs2_val[5..0], - RISCV_ROR => if sizeof(xlen) == 32 - then rs1_val >>> rs2_val[4..0] - else rs1_val >>> rs2_val[5..0] - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: ror +long_name: Rotate right (Register) +description: | + This instruction performs a rotate right of rs1 by the amount in least-significant `log2(XLEN)` bits of rs2. +definedBy: + anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] +assembly: xd, xs1, xs2 +encoding: + match: 0110000----------101-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg shamt = (xlen() == 32) ? X[rs2][4:0] : X[rs2][5:0]; + + X[rd] = (X[rs1] >> shamt) | (X[rs1] << (xlen() - shamt)); + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ANDN => rs1_val & ~(rs2_val), + RISCV_ORN => rs1_val | ~(rs2_val), + RISCV_XNOR => ~(rs1_val ^ rs2_val), + RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), + RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), + RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_ROL => if sizeof(xlen) == 32 + then rs1_val <<< rs2_val[4..0] + else rs1_val <<< rs2_val[5..0], + RISCV_ROR => if sizeof(xlen) == 32 + then rs1_val >>> rs2_val[4..0] + else rs1_val >>> rs2_val[5..0] + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/rori.yaml b/arch/inst/B/rori.yaml index 5902f2d85..d6d41f042 100644 --- a/arch/inst/B/rori.yaml +++ b/arch/inst/B/rori.yaml @@ -1,59 +1,61 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -rori: - long_name: Rotate right (Immediate) - description: | - This instruction performs a rotate right of rs1 by the amount in the least-significant log2(XLEN) bits of shamt. - For RV32, the encodings corresponding to shamt[5]=1 are reserved. - definedBy: - anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] - assembly: xd, xs1, shamt - encoding: - RV32: - match: 0110000----------101-----0110011 - variables: - - name: shamt - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - RV64: - match: 011000-----------101-----0110011 - variables: - - name: shamt - location: 25-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg shamt = (xlen() == 32) ? shamt[4:0] : shamt[5:0]; - - X[rd] = (X[rs1] >> shamt) | (X[rs1] << (xlen() - shamt)); - - - - sail(): | - { - let rs1_val = X(rs1); - let result : xlenbits = if sizeof(xlen) == 32 - then rs1_val >>> shamt[4..0] - else rs1_val >>> shamt; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: rori +long_name: Rotate right (Immediate) +description: | + This instruction performs a rotate right of rs1 by the amount in the least-significant log2(XLEN) bits of shamt. + For RV32, the encodings corresponding to shamt[5]=1 are reserved. +definedBy: + anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] +assembly: xd, xs1, shamt +encoding: + RV32: + match: 0110000----------101-----0110011 + variables: + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 + RV64: + match: 011000-----------101-----0110011 + variables: + - name: shamt + location: 25-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg shamt = (xlen() == 32) ? shamt[4:0] : shamt[5:0]; + + X[rd] = (X[rs1] >> shamt) | (X[rs1] << (xlen() - shamt)); + + + +sail(): | + { + let rs1_val = X(rs1); + let result : xlenbits = if sizeof(xlen) == 32 + then rs1_val >>> shamt[4..0] + else rs1_val >>> shamt; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/roriw.yaml b/arch/inst/B/roriw.yaml index 846d83ce2..7967bc196 100644 --- a/arch/inst/B/roriw.yaml +++ b/arch/inst/B/roriw.yaml @@ -1,50 +1,52 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -roriw: - long_name: Rotate right word (Immediate) - description: | - This instruction performs a rotate right on the least-significant word of rs1 by the amount in - the least-significant log2(XLEN) bits of shamt. The resulting word value is sign-extended by - copying bit 31 to all of the more-significant bits. - definedBy: - anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] - assembly: xd, xs1, shamt - base: 64 - encoding: - match: 0110000----------101-----0011011 - variables: - - name: shamt - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg rs1_word = X[rs1][31:0]; - - XReg unextended_result = (X[rs1] >> shamt) | (X[rs1] << (32 - shamt)); - X[rd] = {{32{unextended_result[31]}}, unextended_result}; - - - - sail(): | - { - let rs1_val = (X(rs1))[31..0]; - let result : xlenbits = sign_extend(rs1_val >>> shamt); - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: roriw +long_name: Rotate right word (Immediate) +description: | + This instruction performs a rotate right on the least-significant word of rs1 by the amount in + the least-significant log2(XLEN) bits of shamt. The resulting word value is sign-extended by + copying bit 31 to all of the more-significant bits. +definedBy: + anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] +assembly: xd, xs1, shamt +base: 64 +encoding: + match: 0110000----------101-----0011011 + variables: + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg rs1_word = X[rs1][31:0]; + + XReg unextended_result = (X[rs1] >> shamt) | (X[rs1] << (32 - shamt)); + X[rd] = {{32{unextended_result[31]}}, unextended_result}; + + + +sail(): | + { + let rs1_val = (X(rs1))[31..0]; + let result : xlenbits = sign_extend(rs1_val >>> shamt); + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/rorw.yaml b/arch/inst/B/rorw.yaml index a34b959e7..9f25c3dc6 100644 --- a/arch/inst/B/rorw.yaml +++ b/arch/inst/B/rorw.yaml @@ -1,55 +1,57 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -rorw: - long_name: Rotate right word (Register) - description: | - This instruction performs a rotate right on the least-significant word of rs1 by the amount in - least-significant 5 bits of rs2. The resultant word is sign-extended by copying bit 31 to all - of the more-significant bits. - definedBy: - anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] - assembly: xd, xs1, xs2 - base: 64 - encoding: - match: 0110000----------101-----0111011 - variables: - - name: shamt - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - XReg rs1_word = X[rs1][31:0]; - XReg shamt = X[rs1][4:0]; - - XReg unextended_result = (X[rs1] >> shamt) | (X[rs1] << (32 - shamt)); - X[rd] = {{32{unextended_result[31]}}, unextended_result}; - - - - sail(): | - { - let rs1_val = (X(rs1))[31..0]; - let shamt = (X(rs2))[4..0]; - let result : bits(32) = match op { - RISCV_ROLW => rs1_val <<< shamt, - RISCV_RORW => rs1_val >>> shamt - }; - X(rd) = sign_extend(result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: rorw +long_name: Rotate right word (Register) +description: | + This instruction performs a rotate right on the least-significant word of rs1 by the amount in + least-significant 5 bits of rs2. The resultant word is sign-extended by copying bit 31 to all + of the more-significant bits. +definedBy: + anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] +assembly: xd, xs1, xs2 +base: 64 +encoding: + match: 0110000----------101-----0111011 + variables: + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg rs1_word = X[rs1][31:0]; + XReg shamt = X[rs1][4:0]; + + XReg unextended_result = (X[rs1] >> shamt) | (X[rs1] << (32 - shamt)); + X[rd] = {{32{unextended_result[31]}}, unextended_result}; + + + +sail(): | + { + let rs1_val = (X(rs1))[31..0]; + let shamt = (X(rs2))[4..0]; + let result : bits(32) = match op { + RISCV_ROLW => rs1_val <<< shamt, + RISCV_RORW => rs1_val >>> shamt + }; + X(rd) = sign_extend(result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/sext.b.yaml b/arch/inst/B/sext.b.yaml index 1bb3625fe..6a7a2018e 100644 --- a/arch/inst/B/sext.b.yaml +++ b/arch/inst/B/sext.b.yaml @@ -1,50 +1,52 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sext.b: - long_name: Sign-extend byte - description: | - This instruction sign-extends the least-significant byte in the source to XLEN by copying the - most-significant bit in the byte (i.e., bit 7) to all of the more-significant bits. - definedBy: - anyOf: [B, Zbb] - assembly: xd, xs1 - encoding: - match: 011000000100-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - if (xlen() == 32) { - X[rd] = {{24{X[rs1][7]}}, X[rs1][7:0]}; - } else if (xlen() == 64) { - X[rd] = {{56{X[rs1][7]}}, X[rs1][7:0]}; - } - - - - sail(): | - { - let rs1_val = X(rs1); - let result : xlenbits = match op { - RISCV_SEXTB => sign_extend(rs1_val[7..0]), - RISCV_SEXTH => sign_extend(rs1_val[15..0]), - RISCV_ZEXTH => zero_extend(rs1_val[15..0]) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sext.b +long_name: Sign-extend byte +description: | + This instruction sign-extends the least-significant byte in the source to XLEN by copying the + most-significant bit in the byte (i.e., bit 7) to all of the more-significant bits. +definedBy: + anyOf: [B, Zbb] +assembly: xd, xs1 +encoding: + match: 011000000100-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + if (xlen() == 32) { + X[rd] = {{24{X[rs1][7]}}, X[rs1][7:0]}; + } else if (xlen() == 64) { + X[rd] = {{56{X[rs1][7]}}, X[rs1][7:0]}; + } + + + +sail(): | + { + let rs1_val = X(rs1); + let result : xlenbits = match op { + RISCV_SEXTB => sign_extend(rs1_val[7..0]), + RISCV_SEXTH => sign_extend(rs1_val[15..0]), + RISCV_ZEXTH => zero_extend(rs1_val[15..0]) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/sext.h.yaml b/arch/inst/B/sext.h.yaml index 88027697b..2ceef5be8 100644 --- a/arch/inst/B/sext.h.yaml +++ b/arch/inst/B/sext.h.yaml @@ -1,50 +1,52 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sext.h: - long_name: Sign-extend halfword - description: | - This instruction sign-extends the least-significant halfword in the source to XLEN by copying the - most-significant bit in the halfword (i.e., bit 15) to all of the more-significant bits. - definedBy: - anyOf: [B, Zbb] - assembly: xd, xs1 - encoding: - match: 011000000101-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - if (xlen() == 32) { - X[rd] = {{16{X[rs1][15]}}, X[rs1][15:0]}; - } else if (xlen() == 64) { - X[rd] = {{48{X[rs1][15]}}, X[rs1][15:0]}; - } - - - - sail(): | - { - let rs1_val = X(rs1); - let result : xlenbits = match op { - RISCV_SEXTB => sign_extend(rs1_val[7..0]), - RISCV_SEXTH => sign_extend(rs1_val[15..0]), - RISCV_ZEXTH => zero_extend(rs1_val[15..0]) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sext.h +long_name: Sign-extend halfword +description: | + This instruction sign-extends the least-significant halfword in the source to XLEN by copying the + most-significant bit in the halfword (i.e., bit 15) to all of the more-significant bits. +definedBy: + anyOf: [B, Zbb] +assembly: xd, xs1 +encoding: + match: 011000000101-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + if (xlen() == 32) { + X[rd] = {{16{X[rs1][15]}}, X[rs1][15:0]}; + } else if (xlen() == 64) { + X[rd] = {{48{X[rs1][15]}}, X[rs1][15:0]}; + } + + + +sail(): | + { + let rs1_val = X(rs1); + let result : xlenbits = match op { + RISCV_SEXTB => sign_extend(rs1_val[7..0]), + RISCV_SEXTH => sign_extend(rs1_val[15..0]), + RISCV_ZEXTH => zero_extend(rs1_val[15..0]) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/sh1add.uw.yaml b/arch/inst/B/sh1add.uw.yaml index a4dbe0955..f85bdb29f 100644 --- a/arch/inst/B/sh1add.uw.yaml +++ b/arch/inst/B/sh1add.uw.yaml @@ -1,53 +1,55 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sh1add.uw: - long_name: Shift unsigend word left by 1 and add - description: | - This instruction performs an XLEN-wide addition of two addends. The first addend is rs2. - The second addend is the unsigned value formed by extracting the least-significant word of rs1 - and shifting it left by 1 place. - definedBy: - anyOf: [B, Zba] - base: 64 - encoding: - match: 0010000----------010-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - assembly: xd, xs1, xs2 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = X[rs2] + (X[rs1][31:0] << 1); - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let shamt : bits(2) = match op { - RISCV_ADDUW => 0b00, - RISCV_SH1ADDUW => 0b01, - RISCV_SH2ADDUW => 0b10, - RISCV_SH3ADDUW => 0b11 - }; - let result : xlenbits = (zero_extend(rs1_val[31..0]) << shamt) + rs2_val; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sh1add.uw +long_name: Shift unsigend word left by 1 and add +description: | + This instruction performs an XLEN-wide addition of two addends. The first addend is rs2. + The second addend is the unsigned value formed by extracting the least-significant word of rs1 + and shifting it left by 1 place. +definedBy: + anyOf: [B, Zba] +base: 64 +encoding: + match: 0010000----------010-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +assembly: xd, xs1, xs2 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = X[rs2] + (X[rs1][31:0] << 1); + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let shamt : bits(2) = match op { + RISCV_ADDUW => 0b00, + RISCV_SH1ADDUW => 0b01, + RISCV_SH2ADDUW => 0b10, + RISCV_SH3ADDUW => 0b11 + }; + let result : xlenbits = (zero_extend(rs1_val[31..0]) << shamt) + rs2_val; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/sh1add.yaml b/arch/inst/B/sh1add.yaml index d57daa99b..472dd48b5 100644 --- a/arch/inst/B/sh1add.yaml +++ b/arch/inst/B/sh1add.yaml @@ -1,49 +1,51 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sh1add: - long_name: Shift left by 1 and add - description: | - This instruction shifts `rs1` to the left by 1 bit and adds it to `rs2`. - definedBy: - anyOf: [B, Zba] - assembly: xd, xs1, xs2 - encoding: - match: 0010000----------010-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = X[rs2] + (X[rs1] << 1); - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let shamt : bits(2) = match op { - RISCV_SH1ADD => 0b01, - RISCV_SH2ADD => 0b10, - RISCV_SH3ADD => 0b11 - }; - let result : xlenbits = (rs1_val << shamt) + rs2_val; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sh1add +long_name: Shift left by 1 and add +description: | + This instruction shifts `rs1` to the left by 1 bit and adds it to `rs2`. +definedBy: + anyOf: [B, Zba] +assembly: xd, xs1, xs2 +encoding: + match: 0010000----------010-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = X[rs2] + (X[rs1] << 1); + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let shamt : bits(2) = match op { + RISCV_SH1ADD => 0b01, + RISCV_SH2ADD => 0b10, + RISCV_SH3ADD => 0b11 + }; + let result : xlenbits = (rs1_val << shamt) + rs2_val; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/sh2add.uw.yaml b/arch/inst/B/sh2add.uw.yaml index 1d1f0964f..a6b6c975d 100644 --- a/arch/inst/B/sh2add.uw.yaml +++ b/arch/inst/B/sh2add.uw.yaml @@ -1,53 +1,55 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sh2add.uw: - long_name: Shift unsigend word left by 2 and add - description: | - This instruction performs an XLEN-wide addition of two addends. The first addend is rs2. - The second addend is the unsigned value formed by extracting the least-significant word of rs1 - and shifting it left by 2 places. - definedBy: - anyOf: [B, Zba] - base: 64 - assembly: xd, xs1, xs2 - encoding: - match: 0010000----------100-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = X[rs2] + (X[rs1][31:0] << 2); - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let shamt : bits(2) = match op { - RISCV_ADDUW => 0b00, - RISCV_SH1ADDUW => 0b01, - RISCV_SH2ADDUW => 0b10, - RISCV_SH3ADDUW => 0b11 - }; - let result : xlenbits = (zero_extend(rs1_val[31..0]) << shamt) + rs2_val; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sh2add.uw +long_name: Shift unsigend word left by 2 and add +description: | + This instruction performs an XLEN-wide addition of two addends. The first addend is rs2. + The second addend is the unsigned value formed by extracting the least-significant word of rs1 + and shifting it left by 2 places. +definedBy: + anyOf: [B, Zba] +base: 64 +assembly: xd, xs1, xs2 +encoding: + match: 0010000----------100-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = X[rs2] + (X[rs1][31:0] << 2); + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let shamt : bits(2) = match op { + RISCV_ADDUW => 0b00, + RISCV_SH1ADDUW => 0b01, + RISCV_SH2ADDUW => 0b10, + RISCV_SH3ADDUW => 0b11 + }; + let result : xlenbits = (zero_extend(rs1_val[31..0]) << shamt) + rs2_val; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/sh2add.yaml b/arch/inst/B/sh2add.yaml index f7bd06c57..952799354 100644 --- a/arch/inst/B/sh2add.yaml +++ b/arch/inst/B/sh2add.yaml @@ -1,49 +1,51 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sh2add: - long_name: Shift left by 2 and add - description: | - This instruction shifts `rs1` to the left by 2 places and adds it to `rs2`. - definedBy: - anyOf: [B, Zba] - assembly: xd, xs1, xs2 - encoding: - match: 0010000----------100-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = X[rs2] + (X[rs1] << 2); - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let shamt : bits(2) = match op { - RISCV_SH1ADD => 0b01, - RISCV_SH2ADD => 0b10, - RISCV_SH3ADD => 0b11 - }; - let result : xlenbits = (rs1_val << shamt) + rs2_val; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sh2add +long_name: Shift left by 2 and add +description: | + This instruction shifts `rs1` to the left by 2 places and adds it to `rs2`. +definedBy: + anyOf: [B, Zba] +assembly: xd, xs1, xs2 +encoding: + match: 0010000----------100-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = X[rs2] + (X[rs1] << 2); + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let shamt : bits(2) = match op { + RISCV_SH1ADD => 0b01, + RISCV_SH2ADD => 0b10, + RISCV_SH3ADD => 0b11 + }; + let result : xlenbits = (rs1_val << shamt) + rs2_val; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/sh3add.uw.yaml b/arch/inst/B/sh3add.uw.yaml index 88fef5a70..7a64f8049 100644 --- a/arch/inst/B/sh3add.uw.yaml +++ b/arch/inst/B/sh3add.uw.yaml @@ -1,53 +1,55 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sh3add.uw: - long_name: Shift unsigend word left by 3 and add - description: | - This instruction performs an XLEN-wide addition of two addends. The first addend is rs2. - The second addend is the unsigned value formed by extracting the least-significant word of rs1 - and shifting it left by 3 places. - definedBy: - anyOf: [B, Zba] - base: 64 - assembly: xd, xs1, xs2 - encoding: - match: 0010000----------110-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = X[rs2] + (X[rs1][31:0] << 3); - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let shamt : bits(2) = match op { - RISCV_ADDUW => 0b00, - RISCV_SH1ADDUW => 0b01, - RISCV_SH2ADDUW => 0b10, - RISCV_SH3ADDUW => 0b11 - }; - let result : xlenbits = (zero_extend(rs1_val[31..0]) << shamt) + rs2_val; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sh3add.uw +long_name: Shift unsigend word left by 3 and add +description: | + This instruction performs an XLEN-wide addition of two addends. The first addend is rs2. + The second addend is the unsigned value formed by extracting the least-significant word of rs1 + and shifting it left by 3 places. +definedBy: + anyOf: [B, Zba] +base: 64 +assembly: xd, xs1, xs2 +encoding: + match: 0010000----------110-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = X[rs2] + (X[rs1][31:0] << 3); + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let shamt : bits(2) = match op { + RISCV_ADDUW => 0b00, + RISCV_SH1ADDUW => 0b01, + RISCV_SH2ADDUW => 0b10, + RISCV_SH3ADDUW => 0b11 + }; + let result : xlenbits = (zero_extend(rs1_val[31..0]) << shamt) + rs2_val; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/sh3add.yaml b/arch/inst/B/sh3add.yaml index cac8ecb02..6f84c5308 100644 --- a/arch/inst/B/sh3add.yaml +++ b/arch/inst/B/sh3add.yaml @@ -1,49 +1,51 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sh3add: - long_name: Shift left by 3 and add - description: | - This instruction shifts `rs1` to the left by 3 places and adds it to `rs2`. - definedBy: - anyOf: [B, Zba] - assembly: xd, xs1, xs2 - encoding: - match: 0010000----------110-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = X[rs2] + (X[rs1] << 3); - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let shamt : bits(2) = match op { - RISCV_SH1ADD => 0b01, - RISCV_SH2ADD => 0b10, - RISCV_SH3ADD => 0b11 - }; - let result : xlenbits = (rs1_val << shamt) + rs2_val; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sh3add +long_name: Shift left by 3 and add +description: | + This instruction shifts `rs1` to the left by 3 places and adds it to `rs2`. +definedBy: + anyOf: [B, Zba] +assembly: xd, xs1, xs2 +encoding: + match: 0010000----------110-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = X[rs2] + (X[rs1] << 3); + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let shamt : bits(2) = match op { + RISCV_SH1ADD => 0b01, + RISCV_SH2ADD => 0b10, + RISCV_SH3ADD => 0b11 + }; + let result : xlenbits = (rs1_val << shamt) + rs2_val; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/slli.uw.yaml b/arch/inst/B/slli.uw.yaml index c0058217d..98e77bad0 100644 --- a/arch/inst/B/slli.uw.yaml +++ b/arch/inst/B/slli.uw.yaml @@ -1,48 +1,50 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -slli.uw: - long_name: Shift left unsigned word (Immediate) - description: | - This instruction takes the least-significant word of rs1, zero-extends it, and shifts it - left by the immediate. - - [NOTE] - This instruction is the same as `slli` with `zext.w` performed on rs1 before shifting. - definedBy: - anyOf: [B, Zba] - base: 64 - encoding: - match: 000010-----------001-----0011011 - variables: - - name: shamt - location: 25-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - assembly: xd, xs1, shamt - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = X[rs1][31:0] << shamt; - - - - sail(): | - { - let rs1_val = X(rs1); - let result : xlenbits = zero_extend(rs1_val[31..0]) << shamt; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: slli.uw +long_name: Shift left unsigned word (Immediate) +description: | + This instruction takes the least-significant word of rs1, zero-extends it, and shifts it + left by the immediate. + + [NOTE] + This instruction is the same as `slli` with `zext.w` performed on rs1 before shifting. +definedBy: + anyOf: [B, Zba] +base: 64 +encoding: + match: 000010-----------001-----0011011 + variables: + - name: shamt + location: 25-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +assembly: xd, xs1, shamt +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = X[rs1][31:0] << shamt; + + + +sail(): | + { + let rs1_val = X(rs1); + let result : xlenbits = zero_extend(rs1_val[31..0]) << shamt; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/xnor.yaml b/arch/inst/B/xnor.yaml index 2a4512fe5..9c5444c3c 100644 --- a/arch/inst/B/xnor.yaml +++ b/arch/inst/B/xnor.yaml @@ -1,59 +1,61 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -xnor: - long_name: Exclusive NOR - description: | - This instruction performs the bit-wise exclusive-NOR operation on rs1 and rs2. - definedBy: - anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] - assembly: xd, xs1, xs2 - encoding: - match: 0100000----------100-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = ~(X[rs1] ^ X[rs2]); - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ANDN => rs1_val & ~(rs2_val), - RISCV_ORN => rs1_val | ~(rs2_val), - RISCV_XNOR => ~(rs1_val ^ rs2_val), - RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), - RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), - RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), - RISCV_ROL => if sizeof(xlen) == 32 - then rs1_val <<< rs2_val[4..0] - else rs1_val <<< rs2_val[5..0], - RISCV_ROR => if sizeof(xlen) == 32 - then rs1_val >>> rs2_val[4..0] - else rs1_val >>> rs2_val[5..0] - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: xnor +long_name: Exclusive NOR +description: | + This instruction performs the bit-wise exclusive-NOR operation on rs1 and rs2. +definedBy: + anyOf: [B, Zbb, Zbkb, Zk, Zkn, Zks] +assembly: xd, xs1, xs2 +encoding: + match: 0100000----------100-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = ~(X[rs1] ^ X[rs2]); + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ANDN => rs1_val & ~(rs2_val), + RISCV_ORN => rs1_val | ~(rs2_val), + RISCV_XNOR => ~(rs1_val ^ rs2_val), + RISCV_MAX => to_bits(sizeof(xlen), max(signed(rs1_val), signed(rs2_val))), + RISCV_MAXU => to_bits(sizeof(xlen), max(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_MIN => to_bits(sizeof(xlen), min(signed(rs1_val), signed(rs2_val))), + RISCV_MINU => to_bits(sizeof(xlen), min(unsigned(rs1_val), unsigned(rs2_val))), + RISCV_ROL => if sizeof(xlen) == 32 + then rs1_val <<< rs2_val[4..0] + else rs1_val <<< rs2_val[5..0], + RISCV_ROR => if sizeof(xlen) == 32 + then rs1_val >>> rs2_val[4..0] + else rs1_val >>> rs2_val[5..0] + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/B/zext.h.yaml b/arch/inst/B/zext.h.yaml index 7bca6dd6a..52c255a37 100644 --- a/arch/inst/B/zext.h.yaml +++ b/arch/inst/B/zext.h.yaml @@ -1,62 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -zext.h: - long_name: Zero-extend halfword - description: | - This instruction zero-extends the least-significant halfword of the source to XLEN by inserting - 0's into all of the bits more significant than 15. - - [NOTE] - The *zext.h* instruction is a pseudo-op for `pack` when `Zbkb` is implemented and XLEN == 32. - - [NOTE] - The *zext.h* instruction is a pseudo-op for `packw` when `Zbkb` is implemented and XLEN == 64. - definedBy: - anyOf: [B, Zbb] - encoding: - RV32: - match: 000010000000-----100-----0110011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - RV64: - match: 000010000000-----100-----0111011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - excludedBy: - anyOf: [Zk, Zkn, Zks, Zbkb] # zext.h instruction is a pseudo-op for `packw` when `Zbkb` is implemented - assembly: xd, xs1 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - X[rd] = X[rs1][15:0]; - - - - sail(): | - { - let rs1_val = X(rs1); - let result : xlenbits = match op { - RISCV_SEXTB => sign_extend(rs1_val[7..0]), - RISCV_SEXTH => sign_extend(rs1_val[15..0]), - RISCV_ZEXTH => zero_extend(rs1_val[15..0]) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: zext.h +long_name: Zero-extend halfword +description: | + This instruction zero-extends the least-significant halfword of the source to XLEN by inserting + 0's into all of the bits more significant than 15. + + [NOTE] + The *zext.h* instruction is a pseudo-op for `pack` when `Zbkb` is implemented and XLEN == 32. + + [NOTE] + The *zext.h* instruction is a pseudo-op for `packw` when `Zbkb` is implemented and XLEN == 64. +definedBy: + anyOf: [B, Zbb] +encoding: + RV32: + match: 000010000000-----100-----0110011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 + RV64: + match: 000010000000-----100-----0111011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +excludedBy: + anyOf: [Zk, Zkn, Zks, Zbkb] # zext.h instruction is a pseudo-op for `packw` when `Zbkb` is implemented +assembly: xd, xs1 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::B) && (CSR[misa].B == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = X[rs1][15:0]; + + + +sail(): | + { + let rs1_val = X(rs1); + let result : xlenbits = match op { + RISCV_SEXTB => sign_extend(rs1_val[7..0]), + RISCV_SEXTH => sign_extend(rs1_val[15..0]), + RISCV_ZEXTH => zero_extend(rs1_val[15..0]) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/C/c.add.yaml b/arch/inst/C/c.add.yaml index 5aca02cb2..0c67ee672 100644 --- a/arch/inst/C/c.add.yaml +++ b/arch/inst/C/c.add.yaml @@ -1,36 +1,38 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.add: - long_name: Add - description: | - Add the value in rs2 to rd, and store the result in rd. - C.ADD expands into `add rd, rd, rs2`. - definedBy: - anyOf: - - C - - Zca - assembly: xd, rs2 - encoding: - match: 1001----------10 - variables: - - name: rs2 - location: 6-2 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg t0 = X[rd]; - XReg t1 = X[rs2]; - X[rd] = t0 + t1; +$schema: "inst_schema.json#" +kind: instruction +name: c.add +long_name: Add +description: | + Add the value in rs2 to rd, and store the result in rd. + C.ADD expands into `add rd, rd, rs2`. +definedBy: + anyOf: + - C + - Zca +assembly: xd, rs2 +encoding: + match: 1001----------10 + variables: + - name: rs2 + location: 6-2 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg t0 = X[rd]; + XReg t1 = X[rs2]; + X[rd] = t0 + t1; - sail(): | - { - let rs1_val = X(rd); - let rs2_val = X(rs2); - X(rd) = rs1_val + rs2_val; - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = X(rd); + let rs2_val = X(rs2); + X(rd) = rs1_val + rs2_val; + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.addi.yaml b/arch/inst/C/c.addi.yaml index f227a49e0..aaab1d707 100644 --- a/arch/inst/C/c.addi.yaml +++ b/arch/inst/C/c.addi.yaml @@ -1,35 +1,37 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.addi: - long_name: Add a sign-extended non-zero immediate - description: | - C.ADDI adds the non-zero sign-extended 6-bit immediate to the value in register rd then writes the result to rd. - C.ADDI expands into `addi rd, rd, imm`. - C.ADDI is only valid when rd≠x0 and imm≠0. - The code points with rd=x0 encode the C.NOP instruction; the remaining code points with imm=0 encode HINTs. - definedBy: - anyOf: - - C - - Zca - assembly: xd, imm - encoding: - match: 000-----------01 - variables: - - name: imm - location: 12|6-2 - not: 0 - - name: rd - location: 11-7 - not: 0 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.addi +long_name: Add a sign-extended non-zero immediate +description: | + C.ADDI adds the non-zero sign-extended 6-bit immediate to the value in register rd then writes the result to rd. + C.ADDI expands into `addi rd, rd, imm`. + C.ADDI is only valid when rd ≠ x0 and imm ≠ 0. + The code points with rd=x0 encode the C.NOP instruction; the remaining code points with imm=0 encode HINTs. +definedBy: + anyOf: + - C + - Zca +assembly: xd, imm +encoding: + match: 000-----------01 + variables: + - name: imm + location: 12|6-2 + not: 0 + - name: rd + location: 11-7 + not: 0 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - X[rd] = X[rd] + imm; + X[rd] = X[rd] + imm; diff --git a/arch/inst/C/c.addi16sp.yaml b/arch/inst/C/c.addi16sp.yaml index 20a079162..d83c81825 100644 --- a/arch/inst/C/c.addi16sp.yaml +++ b/arch/inst/C/c.addi16sp.yaml @@ -1,33 +1,35 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.addi16sp: - long_name: Add a sign-extended non-zero immediate - description: | - C.ADDI16SP adds the non-zero sign-extended 6-bit immediate to the value in the stack pointer (sp=x2), where the immediate is scaled to represent multiples of 16 in the range (-512,496). - C.ADDI16SP is used to adjust the stack pointer in procedure prologues and epilogues. - It expands into `addi x2, x2, nzimm[9:4]`. - C.ADDI16SP is only valid when nzimm≠0; the code point with nzimm=0 is reserved. - definedBy: - anyOf: - - C - - Zca - assembly: imm - encoding: - match: 011-00010-----01 - variables: - - name: imm - location: 12|4-3|5|2|6 - left_shift: 4 - not: 0 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.addi16sp +long_name: Add a sign-extended non-zero immediate +description: | + C.ADDI16SP adds the non-zero sign-extended 6-bit immediate to the value in the stack pointer (sp=x2), where the immediate is scaled to represent multiples of 16 in the range (-512,496). + C.ADDI16SP is used to adjust the stack pointer in procedure prologues and epilogues. + It expands into `addi x2, x2, nzimm[9:4]`. + C.ADDI16SP is only valid when nzimm ≠ 0; the code point with nzimm=0 is reserved. +definedBy: + anyOf: + - C + - Zca +assembly: imm +encoding: + match: 011-00010-----01 + variables: + - name: imm + location: 12|4-3|5|2|6 + left_shift: 4 + not: 0 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - X[2] = X[2] + imm; + X[2] = X[2] + imm; diff --git a/arch/inst/C/c.addi4spn.yaml b/arch/inst/C/c.addi4spn.yaml index ca9d016d7..e1a102e3c 100644 --- a/arch/inst/C/c.addi4spn.yaml +++ b/arch/inst/C/c.addi4spn.yaml @@ -1,35 +1,37 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.addi4spn: - long_name: Add a zero-extended non-zero immediate, scaled by 4, to the stack pointer - description: | - Adds a zero-extended non-zero immediate, scaled by 4, to the stack pointer, x2, and writes the result to rd′. - This instruction is used to generate pointers to stack-allocated variables. - It expands to `addi rd′, x2, nzuimm[9:2]`. - C.ADDI4SPN is only valid when nzuimm≠0; the code points with nzuimm=0 are reserved. - definedBy: - anyOf: - - C - - Zca - assembly: xd, imm - encoding: - match: 000-----------00 - variables: - - name: imm - location: 10-7|12-11|5|6 - left_shift: 2 - not: 0 - - name: rd - location: 4-2 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.addi4spn +long_name: Add a zero-extended non-zero immediate, scaled by 4, to the stack pointer +description: | + Adds a zero-extended non-zero immediate, scaled by 4, to the stack pointer, x2, and writes the result to rd'. + This instruction is used to generate pointers to stack-allocated variables. + It expands to `addi rd', x2, nzuimm[9:2]`. + C.ADDI4SPN is only valid when nzuimm ≠ 0; the code points with nzuimm=0 are reserved. +definedBy: + anyOf: + - C + - Zca +assembly: xd, imm +encoding: + match: 000-----------00 + variables: + - name: imm + location: 10-7|12-11|5|6 + left_shift: 2 + not: 0 + - name: rd + location: 4-2 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - X[rd+8] = X[2] + imm; + X[rd+8] = X[2] + imm; diff --git a/arch/inst/C/c.addiw.yaml b/arch/inst/C/c.addiw.yaml index db1db4cfe..41da2cf8c 100644 --- a/arch/inst/C/c.addiw.yaml +++ b/arch/inst/C/c.addiw.yaml @@ -1,35 +1,37 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.addiw: - long_name: Add a sign-extended non-zero immediate - description: | - C.ADDIW is an RV64C/RV128C-only instruction that performs the same computation as C.ADDI but produces a 32-bit result, then sign-extends result to 64 bits. - C.ADDIW expands into `addiw rd, rd, imm`. - The immediate can be zero for C.ADDIW, where this corresponds to `sext.w rd`. - C.ADDIW is only valid when rd≠x0; the code points with rd=x0 are reserved. - definedBy: - anyOf: - - C - - Zca - base: 64 - assembly: xd, imm - encoding: - match: 001-----------01 - variables: - - name: imm - location: 12|6-2 - - name: rd - location: 11-7 - not: 0 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.addiw +long_name: Add a sign-extended non-zero immediate +description: | + C.ADDIW is an RV64C/RV128C-only instruction that performs the same computation as C.ADDI but produces a 32-bit result, then sign-extends result to 64 bits. + C.ADDIW expands into `addiw rd, rd, imm`. + The immediate can be zero for C.ADDIW, where this corresponds to `sext.w rd`. + C.ADDIW is only valid when rd ≠ x0; the code points with rd=x0 are reserved. +definedBy: + anyOf: + - C + - Zca +base: 64 +assembly: xd, imm +encoding: + match: 001-----------01 + variables: + - name: imm + location: 12|6-2 + - name: rd + location: 11-7 + not: 0 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - X[rd] = sext((X[rd] + imm), 32); + X[rd] = sext((X[rd] + imm), 32); diff --git a/arch/inst/C/c.addw.yaml b/arch/inst/C/c.addw.yaml index 6a93e314d..ec8fe7e01 100644 --- a/arch/inst/C/c.addw.yaml +++ b/arch/inst/C/c.addw.yaml @@ -1,45 +1,47 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.addw: - long_name: Add word - description: | - Add the 32-bit values in rs2 from rd, and store the result in rd. - The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). - C.ADDW expands into `addw rd, rd, rs2`. - definedBy: - anyOf: - - C - - Zca - base: 64 - assembly: xd, rs2 - encoding: - match: 100111---01---01 - variables: - - name: rs2 - location: 4-2 - - name: rd - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - Bits<32> t0 = X[rd+8][31:0]; - Bits<32> t1 = X[rs2+8][31:0]; - X[rd+8] = sext(t0 + t1, 31); +$schema: "inst_schema.json#" +kind: instruction +name: c.addw +long_name: Add word +description: | + Add the 32-bit values in rs2 from rd, and store the result in rd. + The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). + C.ADDW expands into `addw rd, rd, rs2`. +definedBy: + anyOf: + - C + - Zca +base: 64 +assembly: xd, rs2 +encoding: + match: 100111---01---01 + variables: + - name: rs2 + location: 4-2 + - name: rd + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + Bits<32> t0 = X[rd+8][31:0]; + Bits<32> t1 = X[rs2+8][31:0]; + X[rd+8] = sext(t0 + t1, 31); - sail(): | - { - let rs1_val = (X(rd+8))[31..0]; - let rs2_val = (X(rs2+8))[31..0]; - let result : bits(32) = match op { - RISCV_ADDW => rs1_val + rs2_val, - RISCV_SUBW => rs1_val - rs2_val, - RISCV_SLLW => rs1_val << (rs2_val[4..0]), - RISCV_SRLW => rs1_val >> (rs2_val[4..0]), - RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) - }; - X(rd+8) = sign_extend(result); - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = (X(rd+8))[31..0]; + let rs2_val = (X(rs2+8))[31..0]; + let result : bits(32) = match op { + RISCV_ADDW => rs1_val + rs2_val, + RISCV_SUBW => rs1_val - rs2_val, + RISCV_SLLW => rs1_val << (rs2_val[4..0]), + RISCV_SRLW => rs1_val >> (rs2_val[4..0]), + RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) + }; + X(rd+8) = sign_extend(result); + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.and.yaml b/arch/inst/C/c.and.yaml index 4e031c40b..16914a371 100644 --- a/arch/inst/C/c.and.yaml +++ b/arch/inst/C/c.and.yaml @@ -1,55 +1,57 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.and: - long_name: And - description: | - And rd with rs2, and store the result in rd - The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). - C.AND expands into `and rd, rd, rs2`. - definedBy: - anyOf: - - C - - Zca - assembly: xd, rs2 - encoding: - match: 100011---11---01 - variables: - - name: rs2 - location: 4-2 - - name: rd - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg t0 = X[rd+8]; - XReg t1 = X[rs2+8]; - X[rd+8] = t0 & t1; +$schema: "inst_schema.json#" +kind: instruction +name: c.and +long_name: And +description: | + And rd with rs2, and store the result in rd + The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). + C.AND expands into `and rd, rd, rs2`. +definedBy: + anyOf: + - C + - Zca +assembly: xd, rs2 +encoding: + match: 100011---11---01 + variables: + - name: rs2 + location: 4-2 + - name: rd + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg t0 = X[rd+8]; + XReg t1 = X[rs2+8]; + X[rd+8] = t0 & t1; - sail(): | - { - let rs1_val = X(rd+8); - let rs2_val = X(rs2+8); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd+8) = result; - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = X(rd+8); + let rs2_val = X(rs2+8); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd+8) = result; + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.andi.yaml b/arch/inst/C/c.andi.yaml index 746e1c981..53eb4d142 100644 --- a/arch/inst/C/c.andi.yaml +++ b/arch/inst/C/c.andi.yaml @@ -1,44 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.andi: - long_name: And immediate - description: | - And an immediate to the value in rd, and store the result in rd. - The rd register index should be used as rd+8 (registers x8-x15). - C.ANDI expands into `andi rd, rd, imm`. - definedBy: - anyOf: - - C - - Zca - assembly: xd, imm - encoding: - match: 100-10--------01 - variables: - - name: imm - location: 12|6-2 - - name: rd - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - # shamt is between 0-63 - X[rd+8] = X[rd+8] & imm; +$schema: "inst_schema.json#" +kind: instruction +name: c.andi +long_name: And immediate +description: | + And an immediate to the value in rd, and store the result in rd. + The rd register index should be used as rd+8 (registers x8-x15). + C.ANDI expands into `andi rd, rd, imm`. +definedBy: + anyOf: + - C + - Zca +assembly: xd, imm +encoding: + match: 100-10--------01 + variables: + - name: imm + location: 12|6-2 + - name: rd + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + # shamt is between 0-63 + X[rd+8] = X[rd+8] & imm; - sail(): | - { - let rd_val = X(rd+8); - let immext : xlenbits = sign_extend(imm); - let result : xlenbits = match op { - RISCV_ADDI => rd_val + immext, - RISCV_SLTI => zero_extend(bool_to_bits(rd_val <_s immext)), - RISCV_SLTIU => zero_extend(bool_to_bits(rd_val <_u immext)), - RISCV_ANDI => rd_val & immext, - RISCV_ORI => rd_val | immext, - RISCV_XORI => rd_val ^ immext - }; - X(rd+8) = result; - RETIRE_SUCCESS - } +sail(): | + { + let rd_val = X(rd+8); + let immext : xlenbits = sign_extend(imm); + let result : xlenbits = match op { + RISCV_ADDI => rd_val + immext, + RISCV_SLTI => zero_extend(bool_to_bits(rd_val <_s immext)), + RISCV_SLTIU => zero_extend(bool_to_bits(rd_val <_u immext)), + RISCV_ANDI => rd_val & immext, + RISCV_ORI => rd_val | immext, + RISCV_XORI => rd_val ^ immext + }; + X(rd+8) = result; + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.beqz.yaml b/arch/inst/C/c.beqz.yaml index 7b664efa1..b8492708e 100644 --- a/arch/inst/C/c.beqz.yaml +++ b/arch/inst/C/c.beqz.yaml @@ -1,65 +1,67 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.beqz: - long_name: Branch if Equal Zero - description: | - C.BEQZ performs conditional control transfers. The offset is sign-extended and added to the pc to form the branch target address. It can therefore target a ±256 B range. C.BEQZ takes the branch if the value in register rs1′ is zero. - It expands to `beq` `rs1, x0, offset`. - definedBy: - anyOf: - - C - - Zca - assembly: xs1, imm - encoding: - match: 110-----------01 - variables: - - name: imm - location: 12|6-5|2|11-10|4-3 - left_shift: 0 - - name: rs1 - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - if (X[rs1] != 0) { - jump($pc + imm); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.beqz +long_name: Branch if Equal Zero +description: | + C.BEQZ performs conditional control transfers. The offset is sign-extended and added to the pc to form the branch target address. It can therefore target a ±256 B range. C.BEQZ takes the branch if the value in register rs1' is zero. + It expands to `beq` `rs1, x0, offset`. +definedBy: + anyOf: + - C + - Zca +assembly: xs1, imm +encoding: + match: 110-----------01 + variables: + - name: imm + location: 12|6-5|2|11-10|4-3 + left_shift: 0 + - name: rs1 + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (X[rs1] != 0) { + jump($pc + imm); + } - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(0); - let taken : bool = match op { - RISCV_BEQ => rs1_val == rs2_val, - RISCV_BNE => rs1_val != rs2_val, - RISCV_BLT => rs1_val <_s rs2_val, - RISCV_BGE => rs1_val >=_s rs2_val, - RISCV_BLTU => rs1_val <_u rs2_val, - RISCV_BGEU => rs1_val >=_u rs2_val - }; - let t : xlenbits = PC + sign_extend(imm); - if taken then { - /* Extensions get the first checks on the prospective target address. */ - match ext_control_check_pc(t) { - Ext_ControlAddr_Error(e) => { - ext_handle_control_check_error(e); - RETIRE_FAIL - }, - Ext_ControlAddr_OK(target) => { - if bit_to_bool(target[1]) & not(extension("C")) then { - handle_mem_exception(target, E_Fetch_Addr_Align()); - RETIRE_FAIL; - } else { - set_next_pc(target); - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(0); + let taken : bool = match op { + RISCV_BEQ => rs1_val == rs2_val, + RISCV_BNE => rs1_val != rs2_val, + RISCV_BLT => rs1_val <_s rs2_val, + RISCV_BGE => rs1_val >=_s rs2_val, + RISCV_BLTU => rs1_val <_u rs2_val, + RISCV_BGEU => rs1_val >=_u rs2_val + }; + let t : xlenbits = PC + sign_extend(imm); + if taken then { + /* Extensions get the first checks on the prospective target address. */ + match ext_control_check_pc(t) { + Ext_ControlAddr_Error(e) => { + ext_handle_control_check_error(e); + RETIRE_FAIL + }, + Ext_ControlAddr_OK(target) => { + if bit_to_bool(target[1]) & not(extension("C")) then { + handle_mem_exception(target, E_Fetch_Addr_Align()); + RETIRE_FAIL; + } else { + set_next_pc(target); + RETIRE_SUCCESS } } - } else RETIRE_SUCCESS - } + } + } else RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.bnez.yaml b/arch/inst/C/c.bnez.yaml index fb70ea199..df9912750 100644 --- a/arch/inst/C/c.bnez.yaml +++ b/arch/inst/C/c.bnez.yaml @@ -1,65 +1,67 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.bnez: - long_name: Branch if NOT Equal Zero - description: | - C.BEQZ performs conditional control transfers. The offset is sign-extended and added to the pc to form the branch target address. It can therefore target a ±256 B range. C.BEQZ takes the branch if the value in register rs1′ is NOT zero. - It expands to `beq` `rs1, x0, offset`. - definedBy: - anyOf: - - C - - Zca - assembly: xs1, imm - encoding: - match: 111-----------01 - variables: - - name: imm - location: 12|6-5|2|11-10|4-3 - left_shift: 0 - - name: rs1 - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - if (X[rs1] != 0) { - jump($pc + imm); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.bnez +long_name: Branch if NOT Equal Zero +description: | + C.BEQZ performs conditional control transfers. The offset is sign-extended and added to the pc to form the branch target address. It can therefore target a ±256 B range. C.BEQZ takes the branch if the value in register rs1' is NOT zero. + It expands to `beq` `rs1, x0, offset`. +definedBy: + anyOf: + - C + - Zca +assembly: xs1, imm +encoding: + match: 111-----------01 + variables: + - name: imm + location: 12|6-5|2|11-10|4-3 + left_shift: 0 + - name: rs1 + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (X[rs1] != 0) { + jump($pc + imm); + } - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(0); - let taken : bool = match op { - RISCV_BEQ => rs1_val == rs2_val, - RISCV_BNE => rs1_val != rs2_val, - RISCV_BLT => rs1_val <_s rs2_val, - RISCV_BGE => rs1_val >=_s rs2_val, - RISCV_BLTU => rs1_val <_u rs2_val, - RISCV_BGEU => rs1_val >=_u rs2_val - }; - let t : xlenbits = PC + sign_extend(imm); - if taken then { - /* Extensions get the first checks on the prospective target address. */ - match ext_control_check_pc(t) { - Ext_ControlAddr_Error(e) => { - ext_handle_control_check_error(e); - RETIRE_FAIL - }, - Ext_ControlAddr_OK(target) => { - if bit_to_bool(target[1]) & not(extension("C")) then { - handle_mem_exception(target, E_Fetch_Addr_Align()); - RETIRE_FAIL; - } else { - set_next_pc(target); - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(0); + let taken : bool = match op { + RISCV_BEQ => rs1_val == rs2_val, + RISCV_BNE => rs1_val != rs2_val, + RISCV_BLT => rs1_val <_s rs2_val, + RISCV_BGE => rs1_val >=_s rs2_val, + RISCV_BLTU => rs1_val <_u rs2_val, + RISCV_BGEU => rs1_val >=_u rs2_val + }; + let t : xlenbits = PC + sign_extend(imm); + if taken then { + /* Extensions get the first checks on the prospective target address. */ + match ext_control_check_pc(t) { + Ext_ControlAddr_Error(e) => { + ext_handle_control_check_error(e); + RETIRE_FAIL + }, + Ext_ControlAddr_OK(target) => { + if bit_to_bool(target[1]) & not(extension("C")) then { + handle_mem_exception(target, E_Fetch_Addr_Align()); + RETIRE_FAIL; + } else { + set_next_pc(target); + RETIRE_SUCCESS } } - } else RETIRE_SUCCESS - } + } + } else RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.ebreak.yaml b/arch/inst/C/c.ebreak.yaml index a50e09d3f..cb97f8058 100644 --- a/arch/inst/C/c.ebreak.yaml +++ b/arch/inst/C/c.ebreak.yaml @@ -1,44 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.ebreak: - long_name: Breakpoint exception. - description: | - The C.EBREAK instruction is used by debuggers to cause control to be transferred back to - a debugging environment. Unless overridden by an external debug environment, - C.EBREAK raises a breakpoint exception and performs no other operation. +$schema: "inst_schema.json#" +kind: instruction +name: c.ebreak +long_name: Breakpoint exception. +description: | + The C.EBREAK instruction is used by debuggers to cause control to be transferred back to + a debugging environment. Unless overridden by an external debug environment, + C.EBREAK raises a breakpoint exception and performs no other operation. - [NOTE] - As described in the `C` Standard Extension for Compressed Instructions, the `c.ebreak` - instruction performs the same operation as the EBREAK instruction. + [NOTE] + As described in the `C` Standard Extension for Compressed Instructions, the `c.ebreak` + instruction performs the same operation as the EBREAK instruction. - EBREAK causes the receiving privilege mode's epc register to be set to the address of - the EBREAK instruction itself, not the address of the following instruction. - As EBREAK causes a synchronous exception, it is not considered to retire, - and should not increment the `minstret` CSR. - definedBy: - anyOf: - - C - - Zca - assembly: " " - encoding: - match: "1001000000000010" - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - if (TRAP_ON_EBREAK) { - raise_precise(ExceptionCode::Breakpoint, mode(), $pc); - } else { - eei_ebreak(); - } + EBREAK causes the receiving privilege mode's epc register to be set to the address of + the EBREAK instruction itself, not the address of the following instruction. + As EBREAK causes a synchronous exception, it is not considered to retire, + and should not increment the `minstret` CSR. +definedBy: + anyOf: + - C + - Zca +assembly: " " +encoding: + match: "1001000000000010" +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (TRAP_ON_EBREAK) { + raise_precise(ExceptionCode::Breakpoint, mode(), $pc); + } else { + eei_ebreak(); + } - sail(): | - { - handle_mem_exception(PC, E_Breakpoint()); - RETIRE_FAIL - } +sail(): | + { + handle_mem_exception(PC, E_Breakpoint()); + RETIRE_FAIL + } diff --git a/arch/inst/C/c.fld.yaml b/arch/inst/C/c.fld.yaml index 02df88e9b..524c727e1 100644 --- a/arch/inst/C/c.fld.yaml +++ b/arch/inst/C/c.fld.yaml @@ -1,37 +1,39 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.fld: - long_name: Load double-precision - description: | - Loads a double precision floating-point value from memory into register rd. - It computes an effective address by adding the zero-extended offset, scaled by 8, - to the base address in register rs1. - It expands to `fld` `rd, offset(rs1)`. - definedBy: - allOf: - - C - - D - assembly: xd, imm(xs1) - encoding: - match: 001-----------00 - variables: - - name: imm - location: 6-5|12-10 - left_shift: 3 - - name: rd - location: 4-2 - - name: rs1 - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.fld +long_name: Load double-precision +description: | + Loads a double precision floating-point value from memory into register rd. + It computes an effective address by adding the zero-extended offset, scaled by 8, + to the base address in register rs1. + It expands to `fld` `rd, offset(rs1)`. +definedBy: + allOf: + - C + - D +assembly: xd, imm(xs1) +encoding: + match: 001-----------00 + variables: + - name: imm + location: 6-5|12-10 + left_shift: 3 + - name: rd + location: 4-2 + - name: rs1 + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1] + imm; + XReg virtual_address = X[rs1] + imm; - X[rd] = sext(read_memory<64>(virtual_address, $encoding), 64); + X[rd] = sext(read_memory<64>(virtual_address, $encoding), 64); diff --git a/arch/inst/C/c.fldsp.yaml b/arch/inst/C/c.fldsp.yaml index e9151667a..da3ef66fa 100644 --- a/arch/inst/C/c.fldsp.yaml +++ b/arch/inst/C/c.fldsp.yaml @@ -1,38 +1,40 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.fldsp: - long_name: Load doubleword into floating-point register from stack - description: | - Loads a double-precision floating-point value from memory into floating-point register rd. - It computes its effective address by adding the zero-extended offset, scaled by 8, - to the stack pointer, x2. - It expands to `fld` `rd, offset(x2)`. - definedBy: - allOf: - - C - - D - assembly: fd, imm(sp) - encoding: - match: 001-----------10 - variables: - - name: imm - location: 4-2|12|6-5 - left_shift: 3 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - if (implemented?(ExtensionName::D) && (CSR[misa].D == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.fldsp +long_name: Load doubleword into floating-point register from stack +description: | + Loads a double-precision floating-point value from memory into floating-point register rd. + It computes its effective address by adding the zero-extended offset, scaled by 8, + to the stack pointer, x2. + It expands to `fld` `rd, offset(x2)`. +definedBy: + allOf: + - C + - D +assembly: fd, imm(sp) +encoding: + match: 001-----------10 + variables: + - name: imm + location: 4-2|12|6-5 + left_shift: 3 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (implemented?(ExtensionName::D) && (CSR[misa].D == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[2] + imm; + XReg virtual_address = X[2] + imm; - f[rd] = read_memory<64>(virtual_address, $encoding); + f[rd] = read_memory<64>(virtual_address, $encoding); diff --git a/arch/inst/C/c.flw.yaml b/arch/inst/C/c.flw.yaml index 179fce179..44d121ea6 100644 --- a/arch/inst/C/c.flw.yaml +++ b/arch/inst/C/c.flw.yaml @@ -1,37 +1,39 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.flw: - long_name: Load single-precision - description: | - Loads a single precision floating-point value from memory into register rd. - It computes an effective address by adding the zero-extended offset, scaled by 4, - to the base address in register rs1. - It expands to `flw` `rd, offset(rs1)`. - definedBy: - allOf: - - C - - F - assembly: xd, imm(xs1) - encoding: - match: 011-----------00 - variables: - - name: imm - location: 5|12-10|6 - left_shift: 2 - - name: rd - location: 4-2 - - name: rs1 - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.flw +long_name: Load single-precision +description: | + Loads a single precision floating-point value from memory into register rd. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the base address in register rs1. + It expands to `flw` `rd, offset(rs1)`. +definedBy: + allOf: + - C + - F +assembly: xd, imm(xs1) +encoding: + match: 011-----------00 + variables: + - name: imm + location: 5|12-10|6 + left_shift: 2 + - name: rd + location: 4-2 + - name: rs1 + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1] + imm; + XReg virtual_address = X[rs1] + imm; - X[rd] = sext(read_memory<32>(virtual_address, $encoding), 32); + X[rd] = sext(read_memory<32>(virtual_address, $encoding), 32); diff --git a/arch/inst/C/c.flwsp.yaml b/arch/inst/C/c.flwsp.yaml index aff898dfe..a92007cee 100644 --- a/arch/inst/C/c.flwsp.yaml +++ b/arch/inst/C/c.flwsp.yaml @@ -1,38 +1,40 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.flwsp: - long_name: Load word into floating-point register from stack - description: | - Loads a single-precision floating-point value from memory into floating-point register rd. - It computes its effective address by adding the zero-extended offset, scaled by 4, - to the stack pointer, x2. - It expands to `flw` `rd, offset(x2)`. - definedBy: - allOf: - - C - - F - assembly: fd, imm(sp) - encoding: - match: 011-----------10 - variables: - - name: imm - location: 3-2|12|6-4 - left_shift: 2 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - if (implemented?(ExtensionName::F) && (CSR[misa].F == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.flwsp +long_name: Load word into floating-point register from stack +description: | + Loads a single-precision floating-point value from memory into floating-point register rd. + It computes its effective address by adding the zero-extended offset, scaled by 4, + to the stack pointer, x2. + It expands to `flw` `rd, offset(x2)`. +definedBy: + allOf: + - C + - F +assembly: fd, imm(sp) +encoding: + match: 011-----------10 + variables: + - name: imm + location: 3-2|12|6-4 + left_shift: 2 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (implemented?(ExtensionName::F) && (CSR[misa].F == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[2] + imm; + XReg virtual_address = X[2] + imm; - f[rd] = read_memory<32>(virtual_address, $encoding); + f[rd] = read_memory<32>(virtual_address, $encoding); diff --git a/arch/inst/C/c.fsd.yaml b/arch/inst/C/c.fsd.yaml index 6a3ed3f69..4531761b9 100644 --- a/arch/inst/C/c.fsd.yaml +++ b/arch/inst/C/c.fsd.yaml @@ -1,37 +1,39 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.fsd: - long_name: Store double-precision - description: | - Stores a double precision floating-point value in register rs2 to memory. - It computes an effective address by adding the zero-extended offset, scaled by 8, - to the base address in register rs1. - It expands to `fsd` `rs2, offset(rs1)`. - definedBy: - allOf: - - C - - D - assembly: xs2, imm(xs1) - encoding: - match: 101-----------00 - variables: - - name: imm - location: 6-5|12-10 - left_shift: 3 - - name: rs2 - location: 4-2 - - name: rs1 - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.fsd +long_name: Store double-precision +description: | + Stores a double precision floating-point value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 8, + to the base address in register rs1. + It expands to `fsd` `rs2, offset(rs1)`. +definedBy: + allOf: + - C + - D +assembly: xs2, imm(xs1) +encoding: + match: 101-----------00 + variables: + - name: imm + location: 6-5|12-10 + left_shift: 3 + - name: rs2 + location: 4-2 + - name: rs1 + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1] + imm; + XReg virtual_address = X[rs1] + imm; - write_memory<64>(virtual_address, X[rs2], $encoding); + write_memory<64>(virtual_address, X[rs2], $encoding); diff --git a/arch/inst/C/c.fsdsp.yaml b/arch/inst/C/c.fsdsp.yaml index 960e920f1..61c5cb4d3 100644 --- a/arch/inst/C/c.fsdsp.yaml +++ b/arch/inst/C/c.fsdsp.yaml @@ -1,38 +1,40 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.fsdsp: - long_name: Store double-precision value to stack - description: | - Stores a double-precision floating-point value in floating-point register rs2 to memory. - It computes an effective address by adding the zero-extended offset, scaled by 8, - to the stack pointer, x2. - It expands to `fsd` `rs2, offset(x2)`. - definedBy: - allOf: - - C - - D - assembly: fs2, imm(sp) - encoding: - match: 101-----------10 - variables: - - name: imm - location: 9-7|12-10 - left_shift: 3 - - name: rs2 - location: 6-2 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - if (implemented?(ExtensionName::D) && (CSR[misa].D == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.fsdsp +long_name: Store double-precision value to stack +description: | + Stores a double-precision floating-point value in floating-point register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 8, + to the stack pointer, x2. + It expands to `fsd` `rs2, offset(x2)`. +definedBy: + allOf: + - C + - D +assembly: fs2, imm(sp) +encoding: + match: 101-----------10 + variables: + - name: imm + location: 9-7|12-10 + left_shift: 3 + - name: rs2 + location: 6-2 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (implemented?(ExtensionName::D) && (CSR[misa].D == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[2] + imm; + XReg virtual_address = X[2] + imm; - write_memory<64>(virtual_address, f[rs2][63:0], $encoding); + write_memory<64>(virtual_address, f[rs2][63:0], $encoding); diff --git a/arch/inst/C/c.fsw.yaml b/arch/inst/C/c.fsw.yaml index 0ae02e595..e7f258634 100644 --- a/arch/inst/C/c.fsw.yaml +++ b/arch/inst/C/c.fsw.yaml @@ -1,37 +1,39 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.fsw: - long_name: Store single-precision - description: | - Stores a single precision floating-point value in register rs2 to memory. - It computes an effective address by adding the zero-extended offset, scaled by 4, - to the base address in register rs1. - It expands to `fsw` `rs2, offset(rs1)`. - definedBy: - allOf: - - C - - F - assembly: xs2, imm(xs1) - encoding: - match: 111-----------00 - variables: - - name: imm - location: 5|12-10|6 - left_shift: 2 - - name: rs2 - location: 4-2 - - name: rs1 - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.fsw +long_name: Store single-precision +description: | + Stores a single precision floating-point value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the base address in register rs1. + It expands to `fsw` `rs2, offset(rs1)`. +definedBy: + allOf: + - C + - F +assembly: xs2, imm(xs1) +encoding: + match: 111-----------00 + variables: + - name: imm + location: 5|12-10|6 + left_shift: 2 + - name: rs2 + location: 4-2 + - name: rs1 + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1] + imm; + XReg virtual_address = X[rs1] + imm; - write_memory<32>(virtual_address, X[rs2][31:0], $encoding); + write_memory<32>(virtual_address, X[rs2][31:0], $encoding); diff --git a/arch/inst/C/c.fswsp.yaml b/arch/inst/C/c.fswsp.yaml index 837f182ec..e02c29024 100644 --- a/arch/inst/C/c.fswsp.yaml +++ b/arch/inst/C/c.fswsp.yaml @@ -1,38 +1,40 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.fswsp: - long_name: Store single-precision value to stack - description: | - Stores a single-precision floating-point value in floating-point register rs2 to memory. - It computes an effective address by adding the zero-extended offset, scaled by 4, - to the stack pointer, x2. - It expands to `fsw` `rs2, offset(x2)`. - definedBy: - allOf: - - C - - F - assembly: fs2, imm(sp) - encoding: - match: 111-----------10 - variables: - - name: imm - location: 8-7|12-9 - left_shift: 2 - - name: rs2 - location: 6-2 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - if (implemented?(ExtensionName::F) && (CSR[misa].F == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.fswsp +long_name: Store single-precision value to stack +description: | + Stores a single-precision floating-point value in floating-point register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the stack pointer, x2. + It expands to `fsw` `rs2, offset(x2)`. +definedBy: + allOf: + - C + - F +assembly: fs2, imm(sp) +encoding: + match: 111-----------10 + variables: + - name: imm + location: 8-7|12-9 + left_shift: 2 + - name: rs2 + location: 6-2 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (implemented?(ExtensionName::F) && (CSR[misa].F == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[2] + imm; + XReg virtual_address = X[2] + imm; - write_memory<32>(virtual_address, f[rs2][31:0], $encoding); + write_memory<32>(virtual_address, f[rs2][31:0], $encoding); diff --git a/arch/inst/C/c.j.yaml b/arch/inst/C/c.j.yaml index e965e7b40..1a4ba8a41 100644 --- a/arch/inst/C/c.j.yaml +++ b/arch/inst/C/c.j.yaml @@ -1,30 +1,32 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.j: - long_name: Jump - description: | - C.J performs an unconditional control transfer. The offset is sign-extended and added to the pc to form the jump target address. C.J can therefore target a ±2 KiB range. - It expands to `jal` `x0, offset`. - definedBy: - anyOf: - - C - - Zca - assembly: imm - encoding: - match: 101-----------01 - variables: - - name: imm - location: 12|8|10-9|6|7|2|11|5-3 - left_shift: 1 - sign_extend: true - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.j +long_name: Jump +description: | + C.J performs an unconditional control transfer. The offset is sign-extended and added to the pc to form the jump target address. C.J can therefore target a ±2 KiB range. + It expands to `jal` `x0, offset`. +definedBy: + anyOf: + - C + - Zca +assembly: imm +encoding: + match: 101-----------01 + variables: + - name: imm + location: 12|8|10-9|6|7|2|11|5-3 + left_shift: 1 + sign_extend: true +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - jump($pc + imm); + jump($pc + imm); diff --git a/arch/inst/C/c.jal.yaml b/arch/inst/C/c.jal.yaml index 83d0f054b..2b168b001 100644 --- a/arch/inst/C/c.jal.yaml +++ b/arch/inst/C/c.jal.yaml @@ -1,34 +1,36 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.jal: - long_name: Jump and Link - description: | - C.JAL is an RV32C-only instruction that performs the same operation as C.J, but additionally writes the address of the instruction following the jump (pc+2) to the link register, x1. - It expands to `jal` `x1, offset`. - definedBy: - anyOf: - - C - - Zca - base: 32 - assembly: imm - encoding: - match: 001-----------01 - variables: - - name: imm - location: 12|8|10-9|6|7|2|11|5-3 - left_shift: 1 - sign_extend: true - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.jal +long_name: Jump and Link +description: | + C.JAL is an RV32C-only instruction that performs the same operation as C.J, but additionally writes the address of the instruction following the jump (pc+2) to the link register, x1. + It expands to `jal` `x1, offset`. +definedBy: + anyOf: + - C + - Zca +base: 32 +assembly: imm +encoding: + match: 001-----------01 + variables: + - name: imm + location: 12|8|10-9|6|7|2|11|5-3 + left_shift: 1 + sign_extend: true +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg retrun_addr = $pc + 2; + XReg retrun_addr = $pc + 2; - jump_halfword($pc + imm); - X[1] = retrun_addr; + jump_halfword($pc + imm); + X[1] = retrun_addr; diff --git a/arch/inst/C/c.jalr.yaml b/arch/inst/C/c.jalr.yaml index 3b67f974a..5865fceb4 100644 --- a/arch/inst/C/c.jalr.yaml +++ b/arch/inst/C/c.jalr.yaml @@ -1,32 +1,34 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.jalr: - long_name: Jump and Link Register. - description: | - C.JALR (jump and link register) performs the same operation as C.JR, but additionally writes the address of the instruction following the jump (pc+2) to the link register, x1. - C.JALR expands to jalr x1, 0(rs1). - definedBy: - anyOf: - - C - - Zca - assembly: xs1 - encoding: - match: 1001-----0000010 - variables: - - name: rs1 - location: 11-7 - not: 0 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - XReg returnaddr; - returnaddr = $pc + 2; +$schema: "inst_schema.json#" +kind: instruction +name: c.jalr +long_name: Jump and Link Register. +description: | + C.JALR (jump and link register) performs the same operation as C.JR, but additionally writes the address of the instruction following the jump (pc+2) to the link register, x1. + C.JALR expands to jalr x1, 0(rs1). +definedBy: + anyOf: + - C + - Zca +assembly: xs1 +encoding: + match: 1001-----0000010 + variables: + - name: rs1 + location: 11-7 + not: 0 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + XReg returnaddr; + returnaddr = $pc + 2; - jump(X[rs1]); - X[1] = returnaddr; + jump(X[rs1]); + X[1] = returnaddr; diff --git a/arch/inst/C/c.jr.yaml b/arch/inst/C/c.jr.yaml index 7fd3a0861..6342aa3f9 100644 --- a/arch/inst/C/c.jr.yaml +++ b/arch/inst/C/c.jr.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.jr: - long_name: Jump Register - description: | - C.JR (jump register) performs an unconditional control transfer to the address in register rs1. - C.JR expands to jalr x0, 0(rs1). - definedBy: - anyOf: - - C - - Zca - assembly: xs1 - encoding: - match: 1000-----0000010 - variables: - - name: rs1 - location: 11-7 - not: 0 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.jr +long_name: Jump Register +description: | + C.JR (jump register) performs an unconditional control transfer to the address in register rs1. + C.JR expands to jalr x0, 0(rs1). +definedBy: + anyOf: + - C + - Zca +assembly: xs1 +encoding: + match: 1000-----0000010 + variables: + - name: rs1 + location: 11-7 + not: 0 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - jump(X[rs1]); + jump(X[rs1]); diff --git a/arch/inst/C/c.ld.yaml b/arch/inst/C/c.ld.yaml index f2c37603c..f34a728b6 100644 --- a/arch/inst/C/c.ld.yaml +++ b/arch/inst/C/c.ld.yaml @@ -1,65 +1,67 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.ld: - long_name: Load double - description: | - Loads a 64-bit value from memory into register rd. - It computes an effective address by adding the zero-extended offset, scaled by 8, - to the base address in register rs1. - It expands to `ld` `rd, offset(rs1)`. - definedBy: - anyOf: - - C - - Zca - assembly: xd, imm(xs1) - encoding: - match: 011-----------00 - variables: - - name: imm - location: 6-5|12-10 - left_shift: 3 - - name: rd - location: 4-2 - - name: rs1 - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.ld +long_name: Load double +description: | + Loads a 64-bit value from memory into register rd. + It computes an effective address by adding the zero-extended offset, scaled by 8, + to the base address in register rs1. + It expands to `ld` `rd, offset(rs1)`. +definedBy: + anyOf: + - C + - Zca +assembly: xd, imm(xs1) +encoding: + match: 011-----------00 + variables: + - name: imm + location: 6-5|12-10 + left_shift: 3 + - name: rd + location: 4-2 + - name: rs1 + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1] + imm; + XReg virtual_address = X[rs1] + imm; - X[rd] = sext(read_memory<64>(virtual_address, $encoding), 64); + X[rd] = sext(read_memory<64>(virtual_address, $encoding), 64); - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => - match (width) { - BYTE => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), - HALF => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), - WORD => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), - DOUBLE if sizeof(xlen) >= 64 => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), - _ => report_invalid_width(__FILE__, __LINE__, width, "load") - } - } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } } + } diff --git a/arch/inst/C/c.ldsp.yaml b/arch/inst/C/c.ldsp.yaml index 76ef48189..3094c3624 100644 --- a/arch/inst/C/c.ldsp.yaml +++ b/arch/inst/C/c.ldsp.yaml @@ -1,39 +1,41 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.ldsp: - long_name: Load doubleword from stack pointer - description: | - C.LDSP is an RV64C/RV128C-only instruction that loads a 64-bit value from memory - into register rd. - It computes its effective address by adding the zero-extended offset, scaled by 8, - to the stack pointer, x2. - It expands to `ld` `rd, offset(x2)`. - C.LDSP is only valid when rd ≠ x0 the code points with rd=x0 are reserved. - definedBy: - anyOf: - - C - - Zca - base: 64 - assembly: xd, imm(sp) - encoding: - match: 011-----------10 - variables: - - name: imm - location: 4-2|12|6-5 - left_shift: 3 - - name: rd - location: 11-7 - not: 0 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.ldsp +long_name: Load doubleword from stack pointer +description: | + C.LDSP is an RV64C/RV128C-only instruction that loads a 64-bit value from memory + into register rd. + It computes its effective address by adding the zero-extended offset, scaled by 8, + to the stack pointer, x2. + It expands to `ld` `rd, offset(x2)`. + C.LDSP is only valid when rd ≠ x0 the code points with rd=x0 are reserved. +definedBy: + anyOf: + - C + - Zca +base: 64 +assembly: xd, imm(sp) +encoding: + match: 011-----------10 + variables: + - name: imm + location: 4-2|12|6-5 + left_shift: 3 + - name: rd + location: 11-7 + not: 0 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[2] + imm; + XReg virtual_address = X[2] + imm; - X[rd] = read_memory<64>(virtual_address, $encoding); + X[rd] = read_memory<64>(virtual_address, $encoding); diff --git a/arch/inst/C/c.li.yaml b/arch/inst/C/c.li.yaml index d31cca35c..a18ea1bab 100644 --- a/arch/inst/C/c.li.yaml +++ b/arch/inst/C/c.li.yaml @@ -1,33 +1,35 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.li: - long_name: Load the sign-extended 6-bit immediate - description: | - C.LI loads the sign-extended 6-bit immediate, imm, into register rd. - C.LI expands into `addi rd, x0, imm`. - C.LI is only valid when rd≠x0; the code points with rd=x0 encode HINTs. - definedBy: - anyOf: - - C - - Zca - assembly: xd, imm - encoding: - match: 010-----------01 - variables: - - name: imm - location: 12|6-2 - - name: rd - location: 11-7 - not: 0 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.li +long_name: Load the sign-extended 6-bit immediate +description: | + C.LI loads the sign-extended 6-bit immediate, imm, into register rd. + C.LI expands into `addi rd, x0, imm`. + C.LI is only valid when rd ≠ x0; the code points with rd=x0 encode HINTs. +definedBy: + anyOf: + - C + - Zca +assembly: xd, imm +encoding: + match: 010-----------01 + variables: + - name: imm + location: 12|6-2 + - name: rd + location: 11-7 + not: 0 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - X[rd] = imm; + X[rd] = imm; diff --git a/arch/inst/C/c.lq.yaml b/arch/inst/C/c.lq.yaml index 548805342..12dfd8304 100644 --- a/arch/inst/C/c.lq.yaml +++ b/arch/inst/C/c.lq.yaml @@ -1,37 +1,39 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.lq: - long_name: Load quadruple - description: | - Loads a 128-bit value from memory into register rd. - It computes an effective address by adding the zero-extended offset, scaled by 16, - to the base address in register rs1. - It expands to `lq` `rd, offset(rs1)`. - definedBy: - anyOf: - - C - - Zca - assembly: xd, imm(xs1) - encoding: - match: 001-----------00 - variables: - - name: imm - location: 12-11|6-5|10 - left_shift: 4 - - name: rd - location: 4-2 - - name: rs1 - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.lq +long_name: Load quadruple +description: | + Loads a 128-bit value from memory into register rd. + It computes an effective address by adding the zero-extended offset, scaled by 16, + to the base address in register rs1. + It expands to `lq` `rd, offset(rs1)`. +definedBy: + anyOf: + - C + - Zca +assembly: xd, imm(xs1) +encoding: + match: 001-----------00 + variables: + - name: imm + location: 12-11|6-5|10 + left_shift: 4 + - name: rd + location: 4-2 + - name: rs1 + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1] + imm; + XReg virtual_address = X[rs1] + imm; - X[rd] = sext(read_memory<128>(virtual_address, $encoding), 128); + X[rd] = sext(read_memory<128>(virtual_address, $encoding), 128); diff --git a/arch/inst/C/c.lqsp.yaml b/arch/inst/C/c.lqsp.yaml index ba1eb3ba2..937857306 100644 --- a/arch/inst/C/c.lqsp.yaml +++ b/arch/inst/C/c.lqsp.yaml @@ -1,38 +1,40 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.lqsp: - long_name: Load quadruple word from stack pointer - description: | - C.LQSP is an RV128C-only instruction that loads a 128-bit value from memory into register rd. - It computes its effective address by adding the zero-extended offset, scaled by 16, - to the stack pointer, x2. - It expands to `lq` `rd, offset(x2)`. - C.LQSP is only valid when rd ≠ x0 the code points with rd=x0 are reserved. - definedBy: - anyOf: - - C - - Zca - base: 64 - assembly: xd, imm(sp) - encoding: - match: 001-----------10 - variables: - - name: imm - location: 5-2|12|6 - left_shift: 4 - - name: rd - location: 11-7 - not: 0 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.lqsp +long_name: Load quadruple word from stack pointer +description: | + C.LQSP is an RV128C-only instruction that loads a 128-bit value from memory into register rd. + It computes its effective address by adding the zero-extended offset, scaled by 16, + to the stack pointer, x2. + It expands to `lq` `rd, offset(x2)`. + C.LQSP is only valid when rd ≠ x0 the code points with rd=x0 are reserved. +definedBy: + anyOf: + - C + - Zca +base: 64 +assembly: xd, imm(sp) +encoding: + match: 001-----------10 + variables: + - name: imm + location: 5-2|12|6 + left_shift: 4 + - name: rd + location: 11-7 + not: 0 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[2] + imm; + XReg virtual_address = X[2] + imm; - X[rd] = read_memory<128>(virtual_address, $encoding); + X[rd] = read_memory<128>(virtual_address, $encoding); diff --git a/arch/inst/C/c.lui.yaml b/arch/inst/C/c.lui.yaml index ccdca54c5..515c277dd 100644 --- a/arch/inst/C/c.lui.yaml +++ b/arch/inst/C/c.lui.yaml @@ -1,34 +1,37 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.lui: - long_name: Load the non-zero 6-bit immediate field into bits 17–12 of the destination register - description: | - C.LUI loads the non-zero 6-bit immediate field into bits 17–12 of the destination register, clears the bottom 12 bits, and sign-extends bit 17 into all higher bits of the destination. - C.LUI expands into `lui rd, imm`. - C.LUI is only valid when rd≠x0 and rd≠x2, and when the immediate is not equal to zero. - The code points with imm=0 are reserved; the remaining code points with rd=x0 are HINTs; and the remaining code points with rd=x2 correspond to the C.ADDI16SP instruction - definedBy: - anyOf: - - C - - Zca - assembly: xd, imm - encoding: - match: 011-----------01 - variables: - - name: imm - location: 12|6-2 - left_shift: 12 - - name: rd - location: 11-7 - not: [0, 2] - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.lui +long_name: Load the non-zero 6-bit immediate field into bits 17-12 of the destination register +description: | + C.LUI loads the non-zero 6-bit immediate field into bits 17-12 of the destination register, clears the bottom 12 bits, and sign-extends bit 17 into all higher bits of the destination. + C.LUI expands into `lui rd, imm`. + C.LUI is only valid when rd≠x0 and rd≠x2, and when the immediate is not equal to zero. + The code points with imm=0 are reserved; the remaining code points with rd=x0 are HINTs; and the remaining code points with rd=x2 correspond to the C.ADDI16SP instruction +definedBy: + anyOf: + - C + - Zca +assembly: xd, imm +encoding: + match: 011-----------01 + variables: + - name: imm + location: 12|6-2 + left_shift: 12 + - name: rd + location: 11-7 + not: [0, 2] +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = imm; - X[rd] = imm; diff --git a/arch/inst/C/c.lw.yaml b/arch/inst/C/c.lw.yaml index 60cef3383..0fa1b48f4 100644 --- a/arch/inst/C/c.lw.yaml +++ b/arch/inst/C/c.lw.yaml @@ -1,65 +1,67 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.lw: - long_name: Load word - description: | - Loads a 32-bit value from memory into register rd. - It computes an effective address by adding the zero-extended offset, scaled by 4, - to the base address in register rs1. - It expands to `lw` `rd, offset(rs1)`. - definedBy: - anyOf: - - C - - Zca - assembly: xd, imm(xs1) - encoding: - match: 010-----------00 - variables: - - name: imm - location: 5|12-10|6 - left_shift: 2 - - name: rd - location: 4-2 - - name: rs1 - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.lw +long_name: Load word +description: | + Loads a 32-bit value from memory into register rd. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the base address in register rs1. + It expands to `lw` `rd, offset(rs1)`. +definedBy: + anyOf: + - C + - Zca +assembly: xd, imm(xs1) +encoding: + match: 010-----------00 + variables: + - name: imm + location: 5|12-10|6 + left_shift: 2 + - name: rd + location: 4-2 + - name: rs1 + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1] + imm; + XReg virtual_address = X[rs1] + imm; - X[rd] = sext(read_memory<32>(virtual_address, $encoding), 32); + X[rd] = sext(read_memory<32>(virtual_address, $encoding), 32); - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => - match (width) { - BYTE => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), - HALF => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), - WORD => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), - DOUBLE if sizeof(xlen) >= 64 => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), - _ => report_invalid_width(__FILE__, __LINE__, width, "load") - } - } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } } + } diff --git a/arch/inst/C/c.lwsp.yaml b/arch/inst/C/c.lwsp.yaml index c07559e17..93e03f9b1 100644 --- a/arch/inst/C/c.lwsp.yaml +++ b/arch/inst/C/c.lwsp.yaml @@ -1,37 +1,39 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.lwsp: - long_name: Load word from stack pointer - description: | - Loads a 32-bit value from memory into register rd. - It computes an effective address by adding the zero-extended offset, scaled by 4, - to the stack pointer, x2. - It expands to `lw` `rd, offset(x2)`. - C.LWSP is only valid when rd ≠ x0. The code points with rd=x0 are reserved. - definedBy: - anyOf: - - C - - Zca - assembly: xd, imm(sp) - encoding: - match: 010-----------10 - variables: - - name: imm - location: 3-2|12|6-4 - left_shift: 2 - - name: rd - location: 11-7 - not: 0 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.lwsp +long_name: Load word from stack pointer +description: | + Loads a 32-bit value from memory into register rd. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the stack pointer, x2. + It expands to `lw` `rd, offset(x2)`. + C.LWSP is only valid when rd ≠ x0. The code points with rd=x0 are reserved. +definedBy: + anyOf: + - C + - Zca +assembly: xd, imm(sp) +encoding: + match: 010-----------10 + variables: + - name: imm + location: 3-2|12|6-4 + left_shift: 2 + - name: rd + location: 11-7 + not: 0 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[2] + imm; + XReg virtual_address = X[2] + imm; - X[rd] = sext(read_memory<32>(virtual_address, $encoding), 32); + X[rd] = sext(read_memory<32>(virtual_address, $encoding), 32); diff --git a/arch/inst/C/c.mv.yaml b/arch/inst/C/c.mv.yaml index e721f3efd..0bd2a872b 100644 --- a/arch/inst/C/c.mv.yaml +++ b/arch/inst/C/c.mv.yaml @@ -1,39 +1,41 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.mv: - long_name: Move Register - description: | - C.MV (move register) performs copy of the data in register rs2 to register rd - C.MV expands to addi rd, x0, rs2. - definedBy: - anyOf: - - C - - Zca - assembly: xd, xs2 - encoding: - match: 1000----------10 - variables: - - name: rd - location: 11-7 - not: 0 - - name: rs2 - location: 6-2 - not: 0 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.mv +long_name: Move Register +description: | + C.MV (move register) performs copy of the data in register rs2 to register rd + C.MV expands to addi rd, x0, rs2. +definedBy: + anyOf: + - C + - Zca +assembly: xd, xs2 +encoding: + match: 1000----------10 + variables: + - name: rd + location: 11-7 + not: 0 + - name: rs2 + location: 6-2 + not: 0 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - X[rd] = X[rs2]; + X[rd] = X[rs2]; - sail(): | - { - let rs2_val = X(rs2); - X(rs) = rs2_val - RETIRE_SUCCESS - } +sail(): | + { + let rs2_val = X(rs2); + X(rs) = rs2_val + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.nop.yaml b/arch/inst/C/c.nop.yaml index 9ad6df0f0..9fb3e794b 100644 --- a/arch/inst/C/c.nop.yaml +++ b/arch/inst/C/c.nop.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.nop: - long_name: Non-operation - description: | - C.NOP expands into `addi x0, x0, imm`. - definedBy: - anyOf: - - C - - Zca - assembly: imm - encoding: - match: 000-00000-----01 - variables: - - name: imm - location: 12|6-2 - not: 0 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.nop +long_name: Non-operation +description: | + C.NOP expands into `addi x0, x0, imm`. +definedBy: + anyOf: + - C + - Zca +assembly: imm +encoding: + match: 000-00000-----01 + variables: + - name: imm + location: 12|6-2 + not: 0 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } diff --git a/arch/inst/C/c.or.yaml b/arch/inst/C/c.or.yaml index cd6241325..f6899d9aa 100644 --- a/arch/inst/C/c.or.yaml +++ b/arch/inst/C/c.or.yaml @@ -1,55 +1,57 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.or: - long_name: Or - description: | - Or rd with rs2, and store the result in rd - The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). - C.OR expands into `or rd, rd, rs2`. - definedBy: - anyOf: - - C - - Zca - assembly: xd, rs2 - encoding: - match: 100011---10---01 - variables: - - name: rs2 - location: 4-2 - - name: rd - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg t0 = X[rd+8]; - XReg t1 = X[rs2+8]; - X[rd+8] = t0 | t1; +$schema: "inst_schema.json#" +kind: instruction +name: c.or +long_name: Or +description: | + Or rd with rs2, and store the result in rd + The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). + C.OR expands into `or rd, rd, rs2`. +definedBy: + anyOf: + - C + - Zca +assembly: xd, rs2 +encoding: + match: 100011---10---01 + variables: + - name: rs2 + location: 4-2 + - name: rd + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg t0 = X[rd+8]; + XReg t1 = X[rs2+8]; + X[rd+8] = t0 | t1; - sail(): | - { - let rs1_val = X(rd+8); - let rs2_val = X(rs2+8); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd+8) = result; - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = X(rd+8); + let rs2_val = X(rs2+8); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd+8) = result; + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.sd.yaml b/arch/inst/C/c.sd.yaml index 38bc4c4c0..b9cf43c0a 100644 --- a/arch/inst/C/c.sd.yaml +++ b/arch/inst/C/c.sd.yaml @@ -1,37 +1,39 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.sd: - long_name: Store double - description: | - Stores a 64-bit value in register rs2 to memory. - It computes an effective address by adding the zero-extended offset, scaled by 8, - to the base address in register rs1. - It expands to `sd` `rs2, offset(rs1)`. - definedBy: - anyOf: - - C - - Zca - assembly: xs2, imm(xs1) - encoding: - match: 111-----------00 - variables: - - name: imm - location: 6-5|12-10 - left_shift: 3 - - name: rs2 - location: 4-2 - - name: rs1 - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.sd +long_name: Store double +description: | + Stores a 64-bit value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 8, + to the base address in register rs1. + It expands to `sd` `rs2, offset(rs1)`. +definedBy: + anyOf: + - C + - Zca +assembly: xs2, imm(xs1) +encoding: + match: 111-----------00 + variables: + - name: imm + location: 6-5|12-10 + left_shift: 3 + - name: rs2 + location: 4-2 + - name: rs1 + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1] + imm; + XReg virtual_address = X[rs1] + imm; - write_memory<64>(virtual_address, X[rs2], $encoding); + write_memory<64>(virtual_address, X[rs2], $encoding); diff --git a/arch/inst/C/c.sdsp.yaml b/arch/inst/C/c.sdsp.yaml index 6547c765c..9c1f3a4cc 100644 --- a/arch/inst/C/c.sdsp.yaml +++ b/arch/inst/C/c.sdsp.yaml @@ -1,36 +1,38 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.sdsp: - long_name: Store doubleword to stack - description: | - Stores a 64-bit value in register rs2 to memory. - It computes an effective address by adding the zero-extended offset, scaled by 8, - to the stack pointer, x2. - It expands to `sd` `rs2, offset(x2)`. - definedBy: - anyOf: - - C - - Zca - base: 64 - assembly: xs2, imm(sp) - encoding: - match: 111-----------10 - variables: - - name: imm - location: 9-7|12-10 - left_shift: 3 - - name: rs2 - location: 6-2 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.sdsp +long_name: Store doubleword to stack +description: | + Stores a 64-bit value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 8, + to the stack pointer, x2. + It expands to `sd` `rs2, offset(x2)`. +definedBy: + anyOf: + - C + - Zca +base: 64 +assembly: xs2, imm(sp) +encoding: + match: 111-----------10 + variables: + - name: imm + location: 9-7|12-10 + left_shift: 3 + - name: rs2 + location: 6-2 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[2] + imm; + XReg virtual_address = X[2] + imm; - write_memory<64>(virtual_address, X[rs2], $encoding); + write_memory<64>(virtual_address, X[rs2], $encoding); diff --git a/arch/inst/C/c.slli.yaml b/arch/inst/C/c.slli.yaml index 89806a62e..6769be23b 100644 --- a/arch/inst/C/c.slli.yaml +++ b/arch/inst/C/c.slli.yaml @@ -1,51 +1,53 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.slli: - long_name: Shift left logical immediate - description: | - Shift the value in rd left by shamt, and store the result back in rd. - C.SLLI expands into `slli rd, rd, shamt`. - definedBy: - anyOf: - - C - - Zca - assembly: xd, shamt - encoding: - match: 000-----------10 - variables: - - name: shamt - location: 12|6-2 - - name: rd - location: 11-7 - not: 0 - access: - s: always - u: always - vs: always - vu: always - operation(): | - # shamt is between 0-63 - X[rd] = X[rd] << shamt; +$schema: "inst_schema.json#" +kind: instruction +name: c.slli +long_name: Shift left logical immediate +description: | + Shift the value in rd left by shamt, and store the result back in rd. + C.SLLI expands into `slli rd, rd, shamt`. +definedBy: + anyOf: + - C + - Zca +assembly: xd, shamt +encoding: + match: 000-----------10 + variables: + - name: shamt + location: 12|6-2 + - name: rd + location: 11-7 + not: 0 +access: + s: always + u: always + vs: always + vu: always +operation(): | + # shamt is between 0-63 + X[rd] = X[rd] << shamt; + +sail(): | + { + let rd_val = X(rd); + /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ + let result : xlenbits = match op { + RISCV_SLLI => if sizeof(xlen) == 32 + then rd_val << shamt[4..0] + else rd_val << shamt, + RISCV_SRLI => if sizeof(xlen) == 32 + then rd_val >> shamt[4..0] + else rd_val >> shamt, + RISCV_SRAI => if sizeof(xlen) == 32 + then shift_right_arith32(rd_val, shamt[4..0]) + else shift_right_arith64(rd_val, shamt) + }; + X(rd) = result; + RETIRE_SUCCESS + } + - sail(): | - { - let rd_val = X(rd); - /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ - let result : xlenbits = match op { - RISCV_SLLI => if sizeof(xlen) == 32 - then rd_val << shamt[4..0] - else rd_val << shamt, - RISCV_SRLI => if sizeof(xlen) == 32 - then rd_val >> shamt[4..0] - else rd_val >> shamt, - RISCV_SRAI => if sizeof(xlen) == 32 - then shift_right_arith32(rd_val, shamt[4..0]) - else shift_right_arith64(rd_val, shamt) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - diff --git a/arch/inst/C/c.sq.yaml b/arch/inst/C/c.sq.yaml index d7ba2c99d..7fa512768 100644 --- a/arch/inst/C/c.sq.yaml +++ b/arch/inst/C/c.sq.yaml @@ -1,37 +1,39 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.sq: - long_name: Store quadruple - description: | - Stores a 128-bit value in register rs2 to memory. - It computes an effective address by adding the zero-extended offset, scaled by 16, - to the base address in register rs1. - It expands to `sq` `rs2, offset(rs1)`. - definedBy: - anyOf: - - C - - Zca - assembly: xs2, imm(xs1) - encoding: - match: 101-----------00 - variables: - - name: imm - location: 12-11|6-5|10 - left_shift: 4 - - name: rs2 - location: 4-2 - - name: rs1 - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.sq +long_name: Store quadruple +description: | + Stores a 128-bit value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 16, + to the base address in register rs1. + It expands to `sq` `rs2, offset(rs1)`. +definedBy: + anyOf: + - C + - Zca +assembly: xs2, imm(xs1) +encoding: + match: 101-----------00 + variables: + - name: imm + location: 12-11|6-5|10 + left_shift: 4 + - name: rs2 + location: 4-2 + - name: rs1 + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1] + imm; + XReg virtual_address = X[rs1] + imm; - write_memory<128>(virtual_address, X[rs2], $encoding); + write_memory<128>(virtual_address, X[rs2], $encoding); diff --git a/arch/inst/C/c.sqsp.yaml b/arch/inst/C/c.sqsp.yaml index 0213866d1..f2f0e486f 100644 --- a/arch/inst/C/c.sqsp.yaml +++ b/arch/inst/C/c.sqsp.yaml @@ -1,36 +1,38 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.sqsp: - long_name: Store quadruple word to stack - description: | - Stores a 128-bit value in register rs2 to memory. - It computes an effective address by adding the zero-extended offset, scaled by 16, - to the stack pointer, x2. - It expands to `sq` `rs2, offset(x2)`. - definedBy: - anyOf: - - C - - Zca - base: 64 - assembly: xs2, imm(sp) - encoding: - match: 101-----------10 - variables: - - name: imm - location: 10-7|12-11 - left_shift: 4 - - name: rs2 - location: 6-2 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.sqsp +long_name: Store quadruple word to stack +description: | + Stores a 128-bit value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 16, + to the stack pointer, x2. + It expands to `sq` `rs2, offset(x2)`. +definedBy: + anyOf: + - C + - Zca +base: 64 +assembly: xs2, imm(sp) +encoding: + match: 101-----------10 + variables: + - name: imm + location: 10-7|12-11 + left_shift: 4 + - name: rs2 + location: 6-2 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[2] + imm; + XReg virtual_address = X[2] + imm; - write_memory<128>(virtual_address, X[rs2], $encoding); + write_memory<128>(virtual_address, X[rs2], $encoding); diff --git a/arch/inst/C/c.srai.yaml b/arch/inst/C/c.srai.yaml index bca00015b..e0b42444a 100644 --- a/arch/inst/C/c.srai.yaml +++ b/arch/inst/C/c.srai.yaml @@ -1,47 +1,49 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.srai: - long_name: Shift right arithmetical immediate - description: | - Arithmetic shift (the original sign bit is copied into the vacated upper bits) the value in rd right by shamt, and store the result in rd. - The rd register index should be used as rd+8 (registers x8-x15). - C.SRAI expands into `srai rd, rd, shamt`. - definedBy: - anyOf: - - C - - Zca - assembly: xd, shamt - encoding: - match: 100-01--------01 - variables: - - name: shamt - location: 12|6-2 - - name: rd - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - # shamt is between 0-63 - X[rd+8] = X[rd+8] >>> shamt; +$schema: "inst_schema.json#" +kind: instruction +name: c.srai +long_name: Shift right arithmetical immediate +description: | + Arithmetic shift (the original sign bit is copied into the vacated upper bits) the value in rd right by shamt, and store the result in rd. + The rd register index should be used as rd+8 (registers x8-x15). + C.SRAI expands into `srai rd, rd, shamt`. +definedBy: + anyOf: + - C + - Zca +assembly: xd, shamt +encoding: + match: 100-01--------01 + variables: + - name: shamt + location: 12|6-2 + - name: rd + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + # shamt is between 0-63 + X[rd+8] = X[rd+8] >>> shamt; - sail(): | - { - let rd_val = X(rd+8); - /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ - let result : xlenbits = match op { - RISCV_SLLI => if sizeof(xlen) == 32 - then rd_val << shamt[4..0] - else rd_val << shamt, - RISCV_SRLI => if sizeof(xlen) == 32 - then rd_val >> shamt[4..0] - else rd_val >> shamt, - RISCV_SRAI => if sizeof(xlen) == 32 - then shift_right_arith32(rd_val, shamt[4..0]) - else shift_right_arith64(rd_val, shamt) - }; - X(rd+8) = result; - RETIRE_SUCCESS - } +sail(): | + { + let rd_val = X(rd+8); + /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ + let result : xlenbits = match op { + RISCV_SLLI => if sizeof(xlen) == 32 + then rd_val << shamt[4..0] + else rd_val << shamt, + RISCV_SRLI => if sizeof(xlen) == 32 + then rd_val >> shamt[4..0] + else rd_val >> shamt, + RISCV_SRAI => if sizeof(xlen) == 32 + then shift_right_arith32(rd_val, shamt[4..0]) + else shift_right_arith64(rd_val, shamt) + }; + X(rd+8) = result; + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.srli.yaml b/arch/inst/C/c.srli.yaml index c8032af87..63a1a35d7 100644 --- a/arch/inst/C/c.srli.yaml +++ b/arch/inst/C/c.srli.yaml @@ -1,51 +1,53 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.srli: - long_name: Shift right logical immediate - description: | - Shift the value in rd right by shamt, and store the result back in rd. - The rd register index should be used as rd+8 (registers x8-x15). - C.SRLI expands into `srli rd, rd, shamt`. - definedBy: - anyOf: - - C - - Zca - assembly: xd, shamt - encoding: - match: 100-00--------01 - variables: - - name: shamt - location: 12|6-2 - - name: rd - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - # shamt is between 0-63 - X[rd+8] = X[rd+8] >> shamt; +$schema: "inst_schema.json#" +kind: instruction +name: c.srli +long_name: Shift right logical immediate +description: | + Shift the value in rd right by shamt, and store the result back in rd. + The rd register index should be used as rd+8 (registers x8-x15). + C.SRLI expands into `srli rd, rd, shamt`. +definedBy: + anyOf: + - C + - Zca +assembly: xd, shamt +encoding: + match: 100-00--------01 + variables: + - name: shamt + location: 12|6-2 + - name: rd + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + # shamt is between 0-63 + X[rd+8] = X[rd+8] >> shamt; + +sail(): | + { + let rd_val = X(rd+8); + /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ + let result : xlenbits = match op { + RISCV_SLLI => if sizeof(xlen) == 32 + then rd_val << shamt[4..0] + else rd_val << shamt, + RISCV_SRLI => if sizeof(xlen) == 32 + then rd_val >> shamt[4..0] + else rd_val >> shamt, + RISCV_SRAI => if sizeof(xlen) == 32 + then shift_right_arith32(rd_val, shamt[4..0]) + else shift_right_arith64(rd_val, shamt) + }; + X(rd+8) = result; + RETIRE_SUCCESS + } + - sail(): | - { - let rd_val = X(rd+8); - /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ - let result : xlenbits = match op { - RISCV_SLLI => if sizeof(xlen) == 32 - then rd_val << shamt[4..0] - else rd_val << shamt, - RISCV_SRLI => if sizeof(xlen) == 32 - then rd_val >> shamt[4..0] - else rd_val >> shamt, - RISCV_SRAI => if sizeof(xlen) == 32 - then shift_right_arith32(rd_val, shamt[4..0]) - else shift_right_arith64(rd_val, shamt) - }; - X(rd+8) = result; - RETIRE_SUCCESS - } - - diff --git a/arch/inst/C/c.sub.yaml b/arch/inst/C/c.sub.yaml index e853bf4cc..36f233523 100644 --- a/arch/inst/C/c.sub.yaml +++ b/arch/inst/C/c.sub.yaml @@ -1,55 +1,57 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.sub: - long_name: Subtract - description: | - Subtract the value in rs2 from rd, and store the result in rd. - The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). - C.SUB expands into `sub rd, rd, rs2`. - definedBy: - anyOf: - - C - - Zca - assembly: xd, rs2 - encoding: - match: 100011---00---01 - variables: - - name: rs2 - location: 4-2 - - name: rd - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg t0 = X[rd+8]; - XReg t1 = X[rs2+8]; - X[rd+8] = t0 - t1; +$schema: "inst_schema.json#" +kind: instruction +name: c.sub +long_name: Subtract +description: | + Subtract the value in rs2 from rd, and store the result in rd. + The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). + C.SUB expands into `sub rd, rd, rs2`. +definedBy: + anyOf: + - C + - Zca +assembly: xd, rs2 +encoding: + match: 100011---00---01 + variables: + - name: rs2 + location: 4-2 + - name: rd + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg t0 = X[rd+8]; + XReg t1 = X[rs2+8]; + X[rd+8] = t0 - t1; - sail(): | - { - let rs1_val = X(rd+8); - let rs2_val = X(rs2+8); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd+8) = result; - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = X(rd+8); + let rs2_val = X(rs2+8); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd+8) = result; + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.subw.yaml b/arch/inst/C/c.subw.yaml index 10b008446..40c047a13 100644 --- a/arch/inst/C/c.subw.yaml +++ b/arch/inst/C/c.subw.yaml @@ -1,45 +1,47 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.subw: - long_name: Subtract word - description: | - Subtract the 32-bit values in rs2 from rd, and store the result in rd. - The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). - C.SUBW expands into `subw rd, rd, rs2`. - definedBy: - anyOf: - - C - - Zca - base: 64 - assembly: xd, rs2 - encoding: - match: 100111---00---01 - variables: - - name: rs2 - location: 4-2 - - name: rd - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - Bits<32> t0 = X[rd+8][31:0]; - Bits<32> t1 = X[rs2+8][31:0]; - X[rd+8] = sext(t0 - t1, 31); +$schema: "inst_schema.json#" +kind: instruction +name: c.subw +long_name: Subtract word +description: | + Subtract the 32-bit values in rs2 from rd, and store the result in rd. + The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). + C.SUBW expands into `subw rd, rd, rs2`. +definedBy: + anyOf: + - C + - Zca +base: 64 +assembly: xd, rs2 +encoding: + match: 100111---00---01 + variables: + - name: rs2 + location: 4-2 + - name: rd + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + Bits<32> t0 = X[rd+8][31:0]; + Bits<32> t1 = X[rs2+8][31:0]; + X[rd+8] = sext(t0 - t1, 31); - sail(): | - { - let rs1_val = (X(rd+8))[31..0]; - let rs2_val = (X(rs2+8))[31..0]; - let result : bits(32) = match op { - RISCV_ADDW => rs1_val + rs2_val, - RISCV_SUBW => rs1_val - rs2_val, - RISCV_SLLW => rs1_val << (rs2_val[4..0]), - RISCV_SRLW => rs1_val >> (rs2_val[4..0]), - RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) - }; - X(rd+8) = sign_extend(result); - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = (X(rd+8))[31..0]; + let rs2_val = (X(rs2+8))[31..0]; + let result : bits(32) = match op { + RISCV_ADDW => rs1_val + rs2_val, + RISCV_SUBW => rs1_val - rs2_val, + RISCV_SLLW => rs1_val << (rs2_val[4..0]), + RISCV_SRLW => rs1_val >> (rs2_val[4..0]), + RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) + }; + X(rd+8) = sign_extend(result); + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.sw.yaml b/arch/inst/C/c.sw.yaml index 8010aa2fb..c4a7d0858 100644 --- a/arch/inst/C/c.sw.yaml +++ b/arch/inst/C/c.sw.yaml @@ -1,37 +1,39 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.sw: - long_name: Store word - description: | - Stores a 32-bit value in register rs2 to memory. - It computes an effective address by adding the zero-extended offset, scaled by 4, - to the base address in register rs1. - It expands to `sw` `rs2, offset(rs1)`. - definedBy: - anyOf: - - C - - Zca - assembly: xs2, imm(xs1) - encoding: - match: 110-----------00 - variables: - - name: imm - location: 5|12-10|6 - left_shift: 2 - - name: rs2 - location: 4-2 - - name: rs1 - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.sw +long_name: Store word +description: | + Stores a 32-bit value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the base address in register rs1. + It expands to `sw` `rs2, offset(rs1)`. +definedBy: + anyOf: + - C + - Zca +assembly: xs2, imm(xs1) +encoding: + match: 110-----------00 + variables: + - name: imm + location: 5|12-10|6 + left_shift: 2 + - name: rs2 + location: 4-2 + - name: rs1 + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[rs1] + imm; + XReg virtual_address = X[rs1] + imm; - write_memory<32>(virtual_address, X[rs2][31:0], $encoding); + write_memory<32>(virtual_address, X[rs2][31:0], $encoding); diff --git a/arch/inst/C/c.swsp.yaml b/arch/inst/C/c.swsp.yaml index e0a0db87c..1327b350f 100644 --- a/arch/inst/C/c.swsp.yaml +++ b/arch/inst/C/c.swsp.yaml @@ -1,35 +1,37 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.swsp: - long_name: Store word to stack - description: | - Stores a 32-bit value in register rs2 to memory. - It computes an effective address by adding the zero-extended offset, scaled by 4, - to the stack pointer, x2. - It expands to `sw` `rs2, offset(x2)`. - definedBy: - anyOf: - - C - - Zca - assembly: xs2, imm(sp) - encoding: - match: 110-----------10 - variables: - - name: imm - location: 8-7|12-9 - left_shift: 2 - - name: rs2 - location: 6-2 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: c.swsp +long_name: Store word to stack +description: | + Stores a 32-bit value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the stack pointer, x2. + It expands to `sw` `rs2, offset(x2)`. +definedBy: + anyOf: + - C + - Zca +assembly: xs2, imm(sp) +encoding: + match: 110-----------10 + variables: + - name: imm + location: 8-7|12-9 + left_shift: 2 + - name: rs2 + location: 6-2 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg virtual_address = X[2] + imm; + XReg virtual_address = X[2] + imm; - write_memory<32>(virtual_address, X[rs2][31:0], $encoding); + write_memory<32>(virtual_address, X[rs2][31:0], $encoding); diff --git a/arch/inst/C/c.xor.yaml b/arch/inst/C/c.xor.yaml index a5bebb2db..f15a3bae9 100644 --- a/arch/inst/C/c.xor.yaml +++ b/arch/inst/C/c.xor.yaml @@ -1,55 +1,57 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -c.xor: - long_name: Exclusive Or - description: | - Exclusive or rd with rs2, and store the result in rd - The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). - C.XOR expands into `xor rd, rd, rs2`. - definedBy: - anyOf: - - C - - Zca - assembly: xd, rs2 - encoding: - match: 100011---01---01 - variables: - - name: rs2 - location: 4-2 - - name: rd - location: 9-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg t0 = X[rd+8]; - XReg t1 = X[rs2+8]; - X[rd+8] = t0 ^ t1; +$schema: "inst_schema.json#" +kind: instruction +name: c.xor +long_name: Exclusive Or +description: | + Exclusive or rd with rs2, and store the result in rd + The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). + C.XOR expands into `xor rd, rd, rs2`. +definedBy: + anyOf: + - C + - Zca +assembly: xd, rs2 +encoding: + match: 100011---01---01 + variables: + - name: rs2 + location: 4-2 + - name: rd + location: 9-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg t0 = X[rd+8]; + XReg t1 = X[rs2+8]; + X[rd+8] = t0 ^ t1; - sail(): | - { - let rs1_val = X(rd+8); - let rs2_val = X(rs2+8); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd+8) = result; - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = X(rd+8); + let rs2_val = X(rs2+8); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd+8) = result; + RETIRE_SUCCESS + } diff --git a/arch/inst/F/fadd.s.yaml b/arch/inst/F/fadd.s.yaml index 5fe6701c4..d5291ea1e 100644 --- a/arch/inst/F/fadd.s.yaml +++ b/arch/inst/F/fadd.s.yaml @@ -1,54 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fadd.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - assembly: fd, fs1, fs2, rm - encoding: - match: 0000000------------------1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_32b = F_or_X_S(rs1); - let rs2_val_32b = F_or_X_S(rs2); - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_32b) : (bits(5), bits(32)) = match op { - FADD_S => riscv_f32Add (rm_3b, rs1_val_32b, rs2_val_32b), - FSUB_S => riscv_f32Sub (rm_3b, rs1_val_32b, rs2_val_32b), - FMUL_S => riscv_f32Mul (rm_3b, rs1_val_32b, rs2_val_32b), - FDIV_S => riscv_f32Div (rm_3b, rs1_val_32b, rs2_val_32b) - }; - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_32b; - RETIRE_SUCCESS - } +$schema: "inst_schema.json#" +kind: instruction +name: fadd.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +assembly: fd, fs1, fs2, rm +encoding: + match: 0000000------------------1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + + + + +sail(): | + { + let rs1_val_32b = F_or_X_S(rs1); + let rs2_val_32b = F_or_X_S(rs2); + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_32b) : (bits(5), bits(32)) = match op { + FADD_S => riscv_f32Add (rm_3b, rs1_val_32b, rs2_val_32b), + FSUB_S => riscv_f32Sub (rm_3b, rs1_val_32b, rs2_val_32b), + FMUL_S => riscv_f32Mul (rm_3b, rs1_val_32b, rs2_val_32b), + FDIV_S => riscv_f32Div (rm_3b, rs1_val_32b, rs2_val_32b) + }; + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_32b; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fclass.s.yaml b/arch/inst/F/fclass.s.yaml index cd74d7745..29d9505ab 100644 --- a/arch/inst/F/fclass.s.yaml +++ b/arch/inst/F/fclass.s.yaml @@ -1,87 +1,89 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fclass.s: - long_name: Single-precision floating-point classify. - description: | - The `fclass.s` instruction examines the value in floating-point register - _fs1_ and writes to integer register _rd_ a 10-bit mask that indicates - the class of the floating-point number. - The format of the mask is described in the table below. - The corresponding bit in _rd_ will be set if the property is true and - clear otherwise. - All other bits in _rd_ are cleared. - Note that exactly one bit in rd will be set. - `fclass.s` does not set the floating-point exception flags. +$schema: "inst_schema.json#" +kind: instruction +name: fclass.s +long_name: Single-precision floating-point classify. +description: | + The `fclass.s` instruction examines the value in floating-point register + _fs1_ and writes to integer register _rd_ a 10-bit mask that indicates + the class of the floating-point number. + The format of the mask is described in the table below. + The corresponding bit in _rd_ will be set if the property is true and + clear otherwise. + All other bits in _rd_ are cleared. + Note that exactly one bit in rd will be set. + `fclass.s` does not set the floating-point exception flags. - .Format of result of `fclass` instruction. - [%autowidth,float="center",align="center",cols="^,<",options="header",] - |=== - |_rd_ bit |Meaning - |0 |_rs1_ is latexmath:[$-\infty$]. - |1 |_rs1_ is a negative normal number. - |2 |_rs1_ is a negative subnormal number. - |3 |_rs1_ is latexmath:[$-0$]. - |4 |_rs1_ is latexmath:[$+0$]. - |5 |_rs1_ is a positive subnormal number. - |6 |_rs1_ is a positive normal number. - |7 |_rs1_ is latexmath:[$+\infty$]. - |8 |_rs1_ is a signaling NaN. - |9 |_rs1_ is a quiet NaN. - |=== + .Format of result of `fclass` instruction. + [%autowidth,float="center",align="center",cols="^,<",options="header",] + |=== + |_rd_ bit |Meaning + |0 |_rs1_ is latexmath:[$-\infty$]. + |1 |_rs1_ is a negative normal number. + |2 |_rs1_ is a negative subnormal number. + |3 |_rs1_ is latexmath:[$-0$]. + |4 |_rs1_ is latexmath:[$+0$]. + |5 |_rs1_ is a positive subnormal number. + |6 |_rs1_ is a positive normal number. + |7 |_rs1_ is latexmath:[$+\infty$]. + |8 |_rs1_ is a signaling NaN. + |9 |_rs1_ is a quiet NaN. + |=== - definedBy: F - assembly: xd, fs1 - encoding: - match: 111000000000-----001-----1010011 - variables: - - name: fs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - check_f_ok($encoding); +definedBy: F +assembly: xd, fs1 +encoding: + match: 111000000000-----001-----1010011 + variables: + - name: fs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + check_f_ok($encoding); - Bits<32> sp_value = f[fs1][31:0]; + Bits<32> sp_value = f[fs1][31:0]; - if (is_sp_neg_inf?(sp_value)) { - X[rd] = 1 << 0; - } else if (is_sp_neg_norm?(sp_value)) { - X[rd] = 1 << 1; - } else if (is_sp_neg_subnorm?(sp_value)) { - X[rd] = 1 << 2; - } else if (is_sp_neg_zero?(sp_value)) { - X[rd] = 1 << 3; - } else if (is_sp_pos_zero?(sp_value)) { - X[rd] = 1 << 4; - } else if (is_sp_pos_subnorm?(sp_value)) { - X[rd] = 1 << 5; - } else if (is_sp_pos_norm?(sp_value)) { - X[rd] = 1 << 6; - } else if (is_sp_pos_inf?(sp_value)) { - X[rd] = 1 << 7; - } else if (is_sp_signaling_nan?(sp_value)) { - X[rd] = 1 << 8; - } else { - assert(is_sp_quiet_nan?(sp_value), "Unexpected SP value"); - X[rd] = 1 << 9; - } + if (is_sp_neg_inf?(sp_value)) { + X[rd] = 1 << 0; + } else if (is_sp_neg_norm?(sp_value)) { + X[rd] = 1 << 1; + } else if (is_sp_neg_subnorm?(sp_value)) { + X[rd] = 1 << 2; + } else if (is_sp_neg_zero?(sp_value)) { + X[rd] = 1 << 3; + } else if (is_sp_pos_zero?(sp_value)) { + X[rd] = 1 << 4; + } else if (is_sp_pos_subnorm?(sp_value)) { + X[rd] = 1 << 5; + } else if (is_sp_pos_norm?(sp_value)) { + X[rd] = 1 << 6; + } else if (is_sp_pos_inf?(sp_value)) { + X[rd] = 1 << 7; + } else if (is_sp_signaling_nan?(sp_value)) { + X[rd] = 1 << 8; + } else { + assert(is_sp_quiet_nan?(sp_value), "Unexpected SP value"); + X[rd] = 1 << 9; + } - sail(): | - { - let rs1_val_X = X(rs1); - let rd_val_S = rs1_val_X [31..0]; - F(rd) = nan_box (rd_val_S); - RETIRE_SUCCESS - } - - +sail(): | + { + let rs1_val_X = X(rs1); + let rd_val_S = rs1_val_X [31..0]; + F(rd) = nan_box (rd_val_S); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fcvt.l.s.yaml b/arch/inst/F/fcvt.l.s.yaml index b554cad42..a218c623f 100644 --- a/arch/inst/F/fcvt.l.s.yaml +++ b/arch/inst/F/fcvt.l.s.yaml @@ -1,49 +1,51 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.l.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - base: 64 - assembly: xd, fs1, rm - encoding: - match: 110000000010-------------1010011 - variables: - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - assert(sizeof(xlen) >= 64); - let rs1_val_LU = X(rs1)[63..0]; - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.l.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +base: 64 +assembly: xd, fs1, rm +encoding: + match: 110000000010-------------1010011 + variables: + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_S; - RETIRE_SUCCESS - } + + + +sail(): | + { + assert(sizeof(xlen) >= 64); + let rs1_val_LU = X(rs1)[63..0]; + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); + + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_S; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fcvt.lu.s.yaml b/arch/inst/F/fcvt.lu.s.yaml index 08aea300d..262b9ee1f 100644 --- a/arch/inst/F/fcvt.lu.s.yaml +++ b/arch/inst/F/fcvt.lu.s.yaml @@ -1,49 +1,51 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.lu.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - base: 64 - assembly: xd, fs1, rm - encoding: - match: 110000000011-------------1010011 - variables: - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - assert(sizeof(xlen) >= 64); - let rs1_val_LU = X(rs1)[63..0]; - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.lu.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +base: 64 +assembly: xd, fs1, rm +encoding: + match: 110000000011-------------1010011 + variables: + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_S; - RETIRE_SUCCESS - } + + + +sail(): | + { + assert(sizeof(xlen) >= 64); + let rs1_val_LU = X(rs1)[63..0]; + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); + + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_S; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fcvt.s.l.yaml b/arch/inst/F/fcvt.s.l.yaml index c8b44f540..3f1e6f7d8 100644 --- a/arch/inst/F/fcvt.s.l.yaml +++ b/arch/inst/F/fcvt.s.l.yaml @@ -1,49 +1,51 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.s.l: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - base: 64 - assembly: fd, xs1, rm - encoding: - match: 110100000010-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - assert(sizeof(xlen) >= 64); - let rs1_val_LU = X(rs1)[63..0]; - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.s.l +long_name: No synopsis available. +description: | + No description available. +definedBy: F +base: 64 +assembly: fd, xs1, rm +encoding: + match: 110100000010-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_S; - RETIRE_SUCCESS - } + + + +sail(): | + { + assert(sizeof(xlen) >= 64); + let rs1_val_LU = X(rs1)[63..0]; + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); + + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_S; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fcvt.s.lu.yaml b/arch/inst/F/fcvt.s.lu.yaml index 4b4c584b9..ff28f6085 100644 --- a/arch/inst/F/fcvt.s.lu.yaml +++ b/arch/inst/F/fcvt.s.lu.yaml @@ -1,49 +1,51 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.s.lu: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - base: 64 - assembly: fd, xs1, rm - encoding: - match: 110100000011-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - assert(sizeof(xlen) >= 64); - let rs1_val_LU = X(rs1)[63..0]; - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.s.lu +long_name: No synopsis available. +description: | + No description available. +definedBy: F +base: 64 +assembly: fd, xs1, rm +encoding: + match: 110100000011-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_S; - RETIRE_SUCCESS - } + + + +sail(): | + { + assert(sizeof(xlen) >= 64); + let rs1_val_LU = X(rs1)[63..0]; + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); + + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_S; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fcvt.s.w.yaml b/arch/inst/F/fcvt.s.w.yaml index 494042765..b4194fd99 100644 --- a/arch/inst/F/fcvt.s.w.yaml +++ b/arch/inst/F/fcvt.s.w.yaml @@ -1,73 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.s.w: - long_name: Convert signed 32-bit integer to single-precision float - description: | - Converts a 32-bit signed integer in integer register _rs1_ into a floating-point number in - floating-point register _fd_. - - All floating-point to integer and integer to floating-point conversion instructions round - according to the _rm_ field. - A floating-point register can be initialized to floating-point positive zero using - `fcvt.s.w rd, x0`, which will never set any exception flags. - - All floating-point conversion instructions set the Inexact exception flag if the rounded - result differs from the operand value and the Invalid exception flag is not set. - definedBy: F - assembly: fd, xs1 - encoding: - match: 110100000000-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - check_f_ok($encoding); - - Bits<32> int_value = X[rs1]; - - Bits<1> sign = int_value[31]; - - RoundingMode rounding_mode = rm_to_mode(rm, $encoding); - - if ((int_value & 32'h7fff_ffff) == 0) { - X[fd] = (sign == 1) ? packToF32UI(1, 0x9E, 0) : 0; - } else { - Bits<32> absA = (sign == 1) ? -int_value : int_value; - X[fd] = softfloat_normRoundPackToF32( sign, 0x9C, absA, rounding_mode ); - } +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.s.w +long_name: Convert signed 32-bit integer to single-precision float +description: | + Converts a 32-bit signed integer in integer register _rs1_ into a floating-point number in + floating-point register _fd_. + + All floating-point to integer and integer to floating-point conversion instructions round + according to the _rm_ field. + A floating-point register can be initialized to floating-point positive zero using + `fcvt.s.w rd, x0`, which will never set any exception flags. + + All floating-point conversion instructions set the Inexact exception flag if the rounded + result differs from the operand value and the Invalid exception flag is not set. +definedBy: F +assembly: fd, xs1 +encoding: + match: 110100000000-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + check_f_ok($encoding); + + Bits<32> int_value = X[rs1]; + + Bits<1> sign = int_value[31]; + + RoundingMode rounding_mode = rm_to_mode(rm, $encoding); - mark_f_state_dirty(); + if ((int_value & 32'h7fff_ffff) == 0) { + X[fd] = (sign == 1) ? packToF32UI(1, 0x9E, 0) : 0; + } else { + Bits<32> absA = (sign == 1) ? -int_value : int_value; + X[fd] = softfloat_normRoundPackToF32( sign, 0x9C, absA, rounding_mode ); + } + mark_f_state_dirty(); - sail(): | - { - assert(sizeof(xlen) >= 64); - let rs1_val_LU = X(rs1)[63..0]; - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); - - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_S; - RETIRE_SUCCESS - } + +sail(): | + { + assert(sizeof(xlen) >= 64); + let rs1_val_LU = X(rs1)[63..0]; + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); + + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_S; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fcvt.s.wu.yaml b/arch/inst/F/fcvt.s.wu.yaml index 27a205b3b..c8aa4a27b 100644 --- a/arch/inst/F/fcvt.s.wu.yaml +++ b/arch/inst/F/fcvt.s.wu.yaml @@ -1,48 +1,50 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.s.wu: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - assembly: fd, xs1, rm - encoding: - match: 110100000001-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - assert(sizeof(xlen) >= 64); - let rs1_val_LU = X(rs1)[63..0]; - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.s.wu +long_name: No synopsis available. +description: | + No description available. +definedBy: F +assembly: fd, xs1, rm +encoding: + match: 110100000001-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_S; - RETIRE_SUCCESS - } + + + +sail(): | + { + assert(sizeof(xlen) >= 64); + let rs1_val_LU = X(rs1)[63..0]; + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); + + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_S; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fcvt.w.s.yaml b/arch/inst/F/fcvt.w.s.yaml index e8a8f9f97..9763b41d4 100644 --- a/arch/inst/F/fcvt.w.s.yaml +++ b/arch/inst/F/fcvt.w.s.yaml @@ -1,103 +1,105 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.w.s: - long_name: Convert single-precision float to integer word to signed 32-bit integer. - description: | - Converts a floating-point number in floating-point register _fs1_ to a signed 32-bit integer indicates - integer register _rd_. - - For XLEN >32, `fcvt.w.s` sign-extends the 32-bit result to the destination register width. - - If the rounded result is not representable as a 32-bit signed integer, it is clipped to the - nearest value and the invalid flag is set. - - The range of valid inputs and behavior for invalid inputs are: - - [separator="!"] - !=== - ! ! Value - - h! Minimum valid input (after rounding) ! `-2^31` - h! Maximum valid input (after rounding) ! `2^31 - 1` - h! Output for out-of-range negative input ! `-2^31` - h! Output for `-∞` ! `-2^31` - h! Output for out-of-range positive input ! `2^31 - 1` - h! Output for `+∞` for `NaN` ! `2^31 - 1` - !=== - - All floating-point to integer and integer to floating-point conversion instructions round - according to the _rm_ field. - A floating-point register can be initialized to floating-point positive zero using - `fcvt.s.w rd, x0`, which will never set any exception flags. - - All floating-point conversion instructions set the Inexact exception flag if the rounded - result differs from the operand value and the Invalid exception flag is not set. - - definedBy: F - assembly: xd, fs1 - encoding: - match: 110000000000-------------1010011 - variables: - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - check_f_ok($encoding); - - Bits<32> sp_value = f[fs1][31:0]; - - Bits<1> sign = sp_value[31]; - Bits<8> exp = sp_value[30:23]; - Bits<23> sig = sp_value[22:0]; - - RoundingMode rounding_mode = rm_to_mode(rm, $encoding); - - if ( (exp == 0xff) && (sig != 0)) { - sign = 0; - set_fp_flag(FpFlag::NV); - X[rd] = SP_CANONICAL_NAN; - } else { - if (exp != 0) { - sig = sig | 0x00800000; - } - Bits<64> sig64 = sig << 32; - Bits<16> shift_dist = 0xAA - exp; - if (0 < shift_dist) { - sig64 = softfloat_shiftRightJam64(sig64, shift_dist ); - } - X[rd] = softfloat_roundToI32( sign, sig64, rounding_mode ); +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.w.s +long_name: Convert single-precision float to integer word to signed 32-bit integer. +description: | + Converts a floating-point number in floating-point register _fs1_ to a signed 32-bit integer indicates + integer register _rd_. + + For XLEN >32, `fcvt.w.s` sign-extends the 32-bit result to the destination register width. + + If the rounded result is not representable as a 32-bit signed integer, it is clipped to the + nearest value and the invalid flag is set. + + The range of valid inputs and behavior for invalid inputs are: + + [separator="!"] + !=== + ! ! Value + + h! Minimum valid input (after rounding) ! `-2^31` + h! Maximum valid input (after rounding) ! `2^31 - 1` + h! Output for out-of-range negative input ! `-2^31` + h! Output for `-∞` ! `-2^31` + h! Output for out-of-range positive input ! `2^31 - 1` + h! Output for `+∞` for `NaN` ! `2^31 - 1` + !=== + + All floating-point to integer and integer to floating-point conversion instructions round + according to the _rm_ field. + A floating-point register can be initialized to floating-point positive zero using + `fcvt.s.w rd, x0`, which will never set any exception flags. + + All floating-point conversion instructions set the Inexact exception flag if the rounded + result differs from the operand value and the Invalid exception flag is not set. + +definedBy: F +assembly: xd, fs1 +encoding: + match: 110000000000-------------1010011 + variables: + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + check_f_ok($encoding); + + Bits<32> sp_value = f[fs1][31:0]; + + Bits<1> sign = sp_value[31]; + Bits<8> exp = sp_value[30:23]; + Bits<23> sig = sp_value[22:0]; + + RoundingMode rounding_mode = rm_to_mode(rm, $encoding); + + if ( (exp == 0xff) && (sig != 0)) { + sign = 0; + set_fp_flag(FpFlag::NV); + X[rd] = SP_CANONICAL_NAN; + } else { + if (exp != 0) { + sig = sig | 0x00800000; } + Bits<64> sig64 = sig << 32; + Bits<16> shift_dist = 0xAA - exp; + if (0 < shift_dist) { + sig64 = softfloat_shiftRightJam64(sig64, shift_dist ); + } + X[rd] = softfloat_roundToI32( sign, sig64, rounding_mode ); + } - sail(): | - { - assert(sizeof(xlen) >= 64); - let rs1_val_LU = X(rs1)[63..0]; - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); - - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_S; - RETIRE_SUCCESS - } +sail(): | + { + assert(sizeof(xlen) >= 64); + let rs1_val_LU = X(rs1)[63..0]; + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); + + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_S; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fcvt.wu.s.yaml b/arch/inst/F/fcvt.wu.s.yaml index 0c559f711..c8280f82b 100644 --- a/arch/inst/F/fcvt.wu.s.yaml +++ b/arch/inst/F/fcvt.wu.s.yaml @@ -1,48 +1,50 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.wu.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - assembly: xd, fs1, rm - encoding: - match: 110000000001-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - assert(sizeof(xlen) >= 64); - let rs1_val_LU = X(rs1)[63..0]; - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.wu.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +assembly: xd, fs1, rm +encoding: + match: 110000000001-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_S; - RETIRE_SUCCESS - } + + + +sail(): | + { + assert(sizeof(xlen) >= 64); + let rs1_val_LU = X(rs1)[63..0]; + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); + + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_S; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fdiv.s.yaml b/arch/inst/F/fdiv.s.yaml index 9ea50b9be..218271c14 100644 --- a/arch/inst/F/fdiv.s.yaml +++ b/arch/inst/F/fdiv.s.yaml @@ -1,54 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fdiv.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - assembly: fd, fs1, fs2, rm - encoding: - match: 0001100------------------1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_32b = F_or_X_S(rs1); - let rs2_val_32b = F_or_X_S(rs2); - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_32b) : (bits(5), bits(32)) = match op { - FADD_S => riscv_f32Add (rm_3b, rs1_val_32b, rs2_val_32b), - FSUB_S => riscv_f32Sub (rm_3b, rs1_val_32b, rs2_val_32b), - FMUL_S => riscv_f32Mul (rm_3b, rs1_val_32b, rs2_val_32b), - FDIV_S => riscv_f32Div (rm_3b, rs1_val_32b, rs2_val_32b) - }; - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_32b; - RETIRE_SUCCESS - } +$schema: "inst_schema.json#" +kind: instruction +name: fdiv.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +assembly: fd, fs1, fs2, rm +encoding: + match: 0001100------------------1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + + + + +sail(): | + { + let rs1_val_32b = F_or_X_S(rs1); + let rs2_val_32b = F_or_X_S(rs2); + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_32b) : (bits(5), bits(32)) = match op { + FADD_S => riscv_f32Add (rm_3b, rs1_val_32b, rs2_val_32b), + FSUB_S => riscv_f32Sub (rm_3b, rs1_val_32b, rs2_val_32b), + FMUL_S => riscv_f32Mul (rm_3b, rs1_val_32b, rs2_val_32b), + FDIV_S => riscv_f32Div (rm_3b, rs1_val_32b, rs2_val_32b) + }; + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_32b; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/feq.s.yaml b/arch/inst/F/feq.s.yaml index dbd9767f5..b704996ce 100644 --- a/arch/inst/F/feq.s.yaml +++ b/arch/inst/F/feq.s.yaml @@ -1,64 +1,66 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -feq.s: - long_name: Single-precision floating-point equal - description: | - Writes 1 to _rd_ if _fs1_ and _fs2_ are equal, and 0 otherwise. +$schema: "inst_schema.json#" +kind: instruction +name: feq.s +long_name: Single-precision floating-point equal +description: | + Writes 1 to _rd_ if _fs1_ and _fs2_ are equal, and 0 otherwise. - If either operand is NaN, the result is 0 (not equal). If either operand is a signaling NaN, the invalid flag is set. + If either operand is NaN, the result is 0 (not equal). If either operand is a signaling NaN, the invalid flag is set. - Positive zero is considered equal to negative zero. + Positive zero is considered equal to negative zero. - definedBy: F - assembly: xd, fs1, fs2 - encoding: - match: 1010000----------010-----1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - check_f_ok($encoding); +definedBy: F +assembly: xd, fs1, fs2 +encoding: + match: 1010000----------010-----1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + check_f_ok($encoding); - Bits<32> sp_value_a = f[fs1][31:0]; - Bits<32> sp_value_b = f[fs1][31:0]; + Bits<32> sp_value_a = f[fs1][31:0]; + Bits<32> sp_value_b = f[fs1][31:0]; - if (is_sp_nan?(sp_value_a) || is_sp_nan?(sp_value_b)) { - if (is_sp_signaling_nan?(sp_value_a) || is_sp_signaling_nan?(sp_value_b)) { - set_fp_flag(FpFlag::NV); - } - X[rd] = 0; - } else { - X[rd] = ( - (sp_value_a == sp_value_b) - || ((sp_value_a | sp_value_b)[30:0] == 0) # pos 0 is equal to neg zero - ) ? 1 : 0; + if (is_sp_nan?(sp_value_a) || is_sp_nan?(sp_value_b)) { + if (is_sp_signaling_nan?(sp_value_a) || is_sp_signaling_nan?(sp_value_b)) { + set_fp_flag(FpFlag::NV); } + X[rd] = 0; + } else { + X[rd] = ( + (sp_value_a == sp_value_b) + || ((sp_value_a | sp_value_b)[30:0] == 0) # pos 0 is equal to neg zero + ) ? 1 : 0; + } - sail(): | - { - let rs1_val_S = F_or_X_S(rs1); - let rs2_val_S = F_or_X_S(rs2); - - let (fflags, rd_val) : (bits_fflags, bool) = - riscv_f32Le (rs1_val_S, rs2_val_S); - - accrue_fflags(fflags); - X(rd) = zero_extend(bool_to_bits(rd_val)); - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val_S = F_or_X_S(rs1); + let rs2_val_S = F_or_X_S(rs2); + let (fflags, rd_val) : (bits_fflags, bool) = + riscv_f32Le (rs1_val_S, rs2_val_S); + accrue_fflags(fflags); + X(rd) = zero_extend(bool_to_bits(rd_val)); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fle.s.yaml b/arch/inst/F/fle.s.yaml index 0cd959280..79dc623c5 100644 --- a/arch/inst/F/fle.s.yaml +++ b/arch/inst/F/fle.s.yaml @@ -1,65 +1,67 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fle.s: - long_name: Single-precision floating-point less than or equal - description: | - Writes 1 to _rd_ if _fs1_ is less than or equal to _fs2_, and 0 otherwise. +$schema: "inst_schema.json#" +kind: instruction +name: fle.s +long_name: Single-precision floating-point less than or equal +description: | + Writes 1 to _rd_ if _fs1_ is less than or equal to _fs2_, and 0 otherwise. - If either operand is NaN, the result is 0 (not equal). - If either operand is a NaN (signaling or quiet), the invalid flag is set. + If either operand is NaN, the result is 0 (not equal). + If either operand is a NaN (signaling or quiet), the invalid flag is set. - Positive zero and negative zero are considered equal. + Positive zero and negative zero are considered equal. - definedBy: F - assembly: xd, fs1, fs2 - encoding: - match: 1010000----------000-----1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - check_f_ok($encoding); +definedBy: F +assembly: xd, fs1, fs2 +encoding: + match: 1010000----------000-----1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + check_f_ok($encoding); - Bits<32> sp_value_a = f[fs1][31:0]; - Bits<32> sp_value_b = f[fs2][31:0]; + Bits<32> sp_value_a = f[fs1][31:0]; + Bits<32> sp_value_b = f[fs2][31:0]; - if (is_sp_nan?(sp_value_a) || is_sp_nan?(sp_value_b)) { - if (is_sp_signaling_nan?(sp_value_a) || is_sp_signaling_nan?(sp_value_b)) { - set_fp_flag(FpFlag::NV); - } - X[rd] = 0; - } else { - X[rd] = ( - (sp_value_a == sp_value_b) - || ((sp_value_a | sp_value_b)[30:0] == 0) # pos 0 is equal to neg zero - ) ? 1 : 0; + if (is_sp_nan?(sp_value_a) || is_sp_nan?(sp_value_b)) { + if (is_sp_signaling_nan?(sp_value_a) || is_sp_signaling_nan?(sp_value_b)) { + set_fp_flag(FpFlag::NV); } + X[rd] = 0; + } else { + X[rd] = ( + (sp_value_a == sp_value_b) + || ((sp_value_a | sp_value_b)[30:0] == 0) # pos 0 is equal to neg zero + ) ? 1 : 0; + } - sail(): | - { - let rs1_val_S = F_or_X_S(rs1); - let rs2_val_S = F_or_X_S(rs2); - - let (fflags, rd_val) : (bits_fflags, bool) = - riscv_f32Le (rs1_val_S, rs2_val_S); - - accrue_fflags(fflags); - X(rd) = zero_extend(bool_to_bits(rd_val)); - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val_S = F_or_X_S(rs1); + let rs2_val_S = F_or_X_S(rs2); + let (fflags, rd_val) : (bits_fflags, bool) = + riscv_f32Le (rs1_val_S, rs2_val_S); + accrue_fflags(fflags); + X(rd) = zero_extend(bool_to_bits(rd_val)); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fleq.s.yaml b/arch/inst/F/fleq.s.yaml index f1429b54d..0f5b5796a 100644 --- a/arch/inst/F/fleq.s.yaml +++ b/arch/inst/F/fleq.s.yaml @@ -1,44 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fleq.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F, Zfa - assembly: xd, fs1, fs2 - encoding: - match: 1010000----------100-----1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_S = F_S(rs1); - let rs2_val_S = F_S(rs2); +$schema: "inst_schema.json#" +kind: instruction +name: fleq.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F, Zfa +assembly: xd, fs1, fs2 +encoding: + match: 1010000----------100-----1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - let (fflags, rd_val) : (bits_fflags, bool) = - riscv_f32Le_quiet (rs1_val_S, rs2_val_S); - - accrue_fflags(fflags); - X(rd) = zero_extend(bool_to_bits(rd_val)); - RETIRE_SUCCESS - } + + + +sail(): | + { + let rs1_val_S = F_S(rs1); + let rs2_val_S = F_S(rs2); + let (fflags, rd_val) : (bits_fflags, bool) = + riscv_f32Le_quiet (rs1_val_S, rs2_val_S); + accrue_fflags(fflags); + X(rd) = zero_extend(bool_to_bits(rd_val)); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fli.s.yaml b/arch/inst/F/fli.s.yaml index e863560f7..008c13fa8 100644 --- a/arch/inst/F/fli.s.yaml +++ b/arch/inst/F/fli.s.yaml @@ -1,69 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fli.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F, Zfa - assembly: fd, fs1 - encoding: - match: 111100000001-----000-----1010011 - variables: - - name: fs1 - location: 19-15 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fli.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F, Zfa +assembly: fd, fs1 +encoding: + match: 111100000001-----000-----1010011 + variables: + - name: fs1 + location: 19-15 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + - sail(): | - { - let bits : bits(32) = match constantidx { - 0b00000 => { 0xbf800000 }, /* -1.0 */ - 0b00001 => { 0x00800000 }, /* minimum positive normal */ - 0b00010 => { 0x37800000 }, /* 1.0 * 2^-16 */ - 0b00011 => { 0x38000000 }, /* 1.0 * 2^-15 */ - 0b00100 => { 0x3b800000 }, /* 1.0 * 2^-8 */ - 0b00101 => { 0x3c000000 }, /* 1.0 * 2^-7 */ - 0b00110 => { 0x3d800000 }, /* 1.0 * 2^-4 */ - 0b00111 => { 0x3e000000 }, /* 1.0 * 2^-3 */ - 0b01000 => { 0x3e800000 }, /* 0.25 */ - 0b01001 => { 0x3ea00000 }, /* 0.3125 */ - 0b01010 => { 0x3ec00000 }, /* 0.375 */ - 0b01011 => { 0x3ee00000 }, /* 0.4375 */ - 0b01100 => { 0x3f000000 }, /* 0.5 */ - 0b01101 => { 0x3f200000 }, /* 0.625 */ - 0b01110 => { 0x3f400000 }, /* 0.75 */ - 0b01111 => { 0x3f600000 }, /* 0.875 */ - 0b10000 => { 0x3f800000 }, /* 1.0 */ - 0b10001 => { 0x3fa00000 }, /* 1.25 */ - 0b10010 => { 0x3fc00000 }, /* 1.5 */ - 0b10011 => { 0x3fe00000 }, /* 1.75 */ - 0b10100 => { 0x40000000 }, /* 2.0 */ - 0b10101 => { 0x40200000 }, /* 2.5 */ - 0b10110 => { 0x40400000 }, /* 3 */ - 0b10111 => { 0x40800000 }, /* 4 */ - 0b11000 => { 0x41000000 }, /* 8 */ - 0b11001 => { 0x41800000 }, /* 16 */ - 0b11010 => { 0x43000000 }, /* 2^7 */ - 0b11011 => { 0x43800000 }, /* 2^8 */ - 0b11100 => { 0x47000000 }, /* 2^15 */ - 0b11101 => { 0x47800000 }, /* 2^16 */ - 0b11110 => { 0x7f800000 }, /* +inf */ - 0b11111 => { canonical_NaN_S() }, - }; - F_S(rd) = bits; - RETIRE_SUCCESS - } - - +sail(): | + { + let bits : bits(32) = match constantidx { + 0b00000 => { 0xbf800000 }, /* -1.0 */ + 0b00001 => { 0x00800000 }, /* minimum positive normal */ + 0b00010 => { 0x37800000 }, /* 1.0 * 2^-16 */ + 0b00011 => { 0x38000000 }, /* 1.0 * 2^-15 */ + 0b00100 => { 0x3b800000 }, /* 1.0 * 2^-8 */ + 0b00101 => { 0x3c000000 }, /* 1.0 * 2^-7 */ + 0b00110 => { 0x3d800000 }, /* 1.0 * 2^-4 */ + 0b00111 => { 0x3e000000 }, /* 1.0 * 2^-3 */ + 0b01000 => { 0x3e800000 }, /* 0.25 */ + 0b01001 => { 0x3ea00000 }, /* 0.3125 */ + 0b01010 => { 0x3ec00000 }, /* 0.375 */ + 0b01011 => { 0x3ee00000 }, /* 0.4375 */ + 0b01100 => { 0x3f000000 }, /* 0.5 */ + 0b01101 => { 0x3f200000 }, /* 0.625 */ + 0b01110 => { 0x3f400000 }, /* 0.75 */ + 0b01111 => { 0x3f600000 }, /* 0.875 */ + 0b10000 => { 0x3f800000 }, /* 1.0 */ + 0b10001 => { 0x3fa00000 }, /* 1.25 */ + 0b10010 => { 0x3fc00000 }, /* 1.5 */ + 0b10011 => { 0x3fe00000 }, /* 1.75 */ + 0b10100 => { 0x40000000 }, /* 2.0 */ + 0b10101 => { 0x40200000 }, /* 2.5 */ + 0b10110 => { 0x40400000 }, /* 3 */ + 0b10111 => { 0x40800000 }, /* 4 */ + 0b11000 => { 0x41000000 }, /* 8 */ + 0b11001 => { 0x41800000 }, /* 16 */ + 0b11010 => { 0x43000000 }, /* 2^7 */ + 0b11011 => { 0x43800000 }, /* 2^8 */ + 0b11100 => { 0x47000000 }, /* 2^15 */ + 0b11101 => { 0x47800000 }, /* 2^16 */ + 0b11110 => { 0x7f800000 }, /* +inf */ + 0b11111 => { canonical_NaN_S() }, + }; + F_S(rd) = bits; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/flt.s.yaml b/arch/inst/F/flt.s.yaml index 055870024..e18c36b47 100644 --- a/arch/inst/F/flt.s.yaml +++ b/arch/inst/F/flt.s.yaml @@ -1,67 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -flt.s: - long_name: Single-precision floating-point less than - description: | - Writes 1 to _rd_ if _fs1_ is less than _fs2_, and 0 otherwise. +$schema: "inst_schema.json#" +kind: instruction +name: flt.s +long_name: Single-precision floating-point less than +description: | + Writes 1 to _rd_ if _fs1_ is less than _fs2_, and 0 otherwise. - If either operand is NaN, the result is 0 (not equal). - If either operand is a NaN (signaling or quiet), the invalid flag is set. + If either operand is NaN, the result is 0 (not equal). + If either operand is a NaN (signaling or quiet), the invalid flag is set. - definedBy: F - assembly: xd, fs1, fs2 - encoding: - match: 1010000----------001-----1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - check_f_ok($encoding); +definedBy: F +assembly: xd, fs1, fs2 +encoding: + match: 1010000----------001-----1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + check_f_ok($encoding); - Bits<32> sp_value_a = f[fs1][31:0]; - Bits<32> sp_value_b = f[fs2][31:0]; + Bits<32> sp_value_a = f[fs1][31:0]; + Bits<32> sp_value_b = f[fs2][31:0]; - if (is_sp_nan?(sp_value_a) || is_sp_nan?(sp_value_b)) { - set_fp_flag(FpFlag::NV); - X[rd] = 0; - } else { - Boolean sign_a = sp_value_a[31] == 1; - Boolean sign_b = sp_value_b[31] == 1; + if (is_sp_nan?(sp_value_a) || is_sp_nan?(sp_value_b)) { + set_fp_flag(FpFlag::NV); + X[rd] = 0; + } else { + Boolean sign_a = sp_value_a[31] == 1; + Boolean sign_b = sp_value_b[31] == 1; - Boolean a_lt_b = - (sign_a != sign_b) - ? (sign_a && ((sp_value_a[30:0] | sp_value_b[30:0]) != 0)) # opposite sign, a is negative. a is less than b as long as both are not zero - : ((sp_value_a != sp_value_b) && (sign_a != (sp_value_a < sp_value_b))); - X[rd] = a_lt_b ? 1 : 0; - } + Boolean a_lt_b = + (sign_a != sign_b) + ? (sign_a && ((sp_value_a[30:0] | sp_value_b[30:0]) != 0)) # opposite sign, a is negative. a is less than b as long as both are not zero + : ((sp_value_a != sp_value_b) && (sign_a != (sp_value_a < sp_value_b))); + X[rd] = a_lt_b ? 1 : 0; + } - sail(): | - { - let rs1_val_S = F_or_X_S(rs1); - let rs2_val_S = F_or_X_S(rs2); - - let (fflags, rd_val) : (bits_fflags, bool) = - riscv_f32Le (rs1_val_S, rs2_val_S); - - accrue_fflags(fflags); - X(rd) = zero_extend(bool_to_bits(rd_val)); - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val_S = F_or_X_S(rs1); + let rs2_val_S = F_or_X_S(rs2); + let (fflags, rd_val) : (bits_fflags, bool) = + riscv_f32Le (rs1_val_S, rs2_val_S); + accrue_fflags(fflags); + X(rd) = zero_extend(bool_to_bits(rd_val)); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fltq.s.yaml b/arch/inst/F/fltq.s.yaml index 37a0341cf..fcda54723 100644 --- a/arch/inst/F/fltq.s.yaml +++ b/arch/inst/F/fltq.s.yaml @@ -1,44 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fltq.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F, Zfa - assembly: xd, fs1, fs2 - encoding: - match: 1010000----------101-----1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_S = F_S(rs1); - let rs2_val_S = F_S(rs2); +$schema: "inst_schema.json#" +kind: instruction +name: fltq.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F, Zfa +assembly: xd, fs1, fs2 +encoding: + match: 1010000----------101-----1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - let (fflags, rd_val) : (bits_fflags, bool) = - riscv_f32Lt_quiet (rs1_val_S, rs2_val_S); - - accrue_fflags(fflags); - X(rd) = zero_extend(bool_to_bits(rd_val)); - RETIRE_SUCCESS - } + + + +sail(): | + { + let rs1_val_S = F_S(rs1); + let rs2_val_S = F_S(rs2); + let (fflags, rd_val) : (bits_fflags, bool) = + riscv_f32Lt_quiet (rs1_val_S, rs2_val_S); + accrue_fflags(fflags); + X(rd) = zero_extend(bool_to_bits(rd_val)); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/flw.yaml b/arch/inst/F/flw.yaml index b120cac93..700f79d00 100644 --- a/arch/inst/F/flw.yaml +++ b/arch/inst/F/flw.yaml @@ -1,74 +1,76 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -flw: - long_name: Single-precision floating-point load - description: | - The `flw` instruction loads a single-precision floating-point value from memory at address _rs1_ + _imm_ into floating-point register _fd_. +$schema: "inst_schema.json#" +kind: instruction +name: flw +long_name: Single-precision floating-point load +description: | + The `flw` instruction loads a single-precision floating-point value from memory at address _rs1_ + _imm_ into floating-point register _fd_. - `flw` does not modify the bits being transferred; in particular, the payloads of non-canonical NaNs are preserved. + `flw` does not modify the bits being transferred; in particular, the payloads of non-canonical NaNs are preserved. - definedBy: F - assembly: fd, xs1, imm - encoding: - match: -----------------010-----0000111 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - check_f_ok($encoding); +definedBy: F +assembly: fd, xs1, imm +encoding: + match: -----------------010-----0000111 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + check_f_ok($encoding); - XReg virtual_address = X[rs1] + $signed(imm); + XReg virtual_address = X[rs1] + $signed(imm); - Bits<32> sp_value = read_memory<32>(virtual_address, $encoding); + Bits<32> sp_value = read_memory<32>(virtual_address, $encoding); - if (implemented?(ExtensionName::D)) { - f[fd] = nan_box<32, 64>(sp_value); - } else { - f[fd] = sp_value; - } + if (implemented?(ExtensionName::D)) { + f[fd] = nan_box<32, 64>(sp_value); + } else { + f[fd] = sp_value; + } - mark_f_state_dirty(); + mark_f_state_dirty(); - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let (aq, rl, res) = (false, false, false); - match (width) { - BYTE => { handle_illegal(); RETIRE_FAIL }, - HALF => - process_fload16(rd, vaddr, mem_read(Read(Data), addr, 2, aq, rl, res)), - WORD => - process_fload32(rd, vaddr, mem_read(Read(Data), addr, 4, aq, rl, res)), - DOUBLE if sizeof(flen) >= 64 => - process_fload64(rd, vaddr, mem_read(Read(Data), addr, 8, aq, rl, res)), - _ => report_invalid_width(__FILE__, __LINE__, width, "floating point load"), - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let (aq, rl, res) = (false, false, false); + match (width) { + BYTE => { handle_illegal(); RETIRE_FAIL }, + HALF => + process_fload16(rd, vaddr, mem_read(Read(Data), addr, 2, aq, rl, res)), + WORD => + process_fload32(rd, vaddr, mem_read(Read(Data), addr, 4, aq, rl, res)), + DOUBLE if sizeof(flen) >= 64 => + process_fload64(rd, vaddr, mem_read(Read(Data), addr, 8, aq, rl, res)), + _ => report_invalid_width(__FILE__, __LINE__, width, "floating point load"), } } - } + } } - - + } + + diff --git a/arch/inst/F/fmadd.s.yaml b/arch/inst/F/fmadd.s.yaml index 7a42d5d03..54ac1e3d4 100644 --- a/arch/inst/F/fmadd.s.yaml +++ b/arch/inst/F/fmadd.s.yaml @@ -1,58 +1,60 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmadd.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - assembly: fd, fs1, fs2, fs3, rm - encoding: - match: -----00------------------1000011 - variables: - - name: fs3 - location: 31-27 - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_32b = F_or_X_S(rs1); - let rs2_val_32b = F_or_X_S(rs2); - let rs3_val_32b = F_or_X_S(rs3); - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_32b) : (bits(5), bits(32)) = - match op { - FMADD_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, rs3_val_32b), - FMSUB_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, negate_S (rs3_val_32b)), - FNMSUB_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, rs3_val_32b), - FNMADD_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, negate_S (rs3_val_32b)) - }; - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_32b; - RETIRE_SUCCESS - } +$schema: "inst_schema.json#" +kind: instruction +name: fmadd.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +assembly: fd, fs1, fs2, fs3, rm +encoding: + match: -----00------------------1000011 + variables: + - name: fs3 + location: 31-27 + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + + + + +sail(): | + { + let rs1_val_32b = F_or_X_S(rs1); + let rs2_val_32b = F_or_X_S(rs2); + let rs3_val_32b = F_or_X_S(rs3); + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_32b) : (bits(5), bits(32)) = + match op { + FMADD_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, rs3_val_32b), + FMSUB_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, negate_S (rs3_val_32b)), + FNMSUB_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, rs3_val_32b), + FNMADD_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, negate_S (rs3_val_32b)) + }; + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_32b; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fmax.s.yaml b/arch/inst/F/fmax.s.yaml index 1be7f1646..9a7ade26b 100644 --- a/arch/inst/F/fmax.s.yaml +++ b/arch/inst/F/fmax.s.yaml @@ -1,44 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmax.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - assembly: fd, fs1, fs2 - encoding: - match: 0010100----------001-----1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_S = F_or_X_S(rs1); - let rs2_val_S = F_or_X_S(rs2); +$schema: "inst_schema.json#" +kind: instruction +name: fmax.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +assembly: fd, fs1, fs2 +encoding: + match: 0010100----------001-----1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - let (fflags, rd_val) : (bits_fflags, bool) = - riscv_f32Le (rs1_val_S, rs2_val_S); - - accrue_fflags(fflags); - X(rd) = zero_extend(bool_to_bits(rd_val)); - RETIRE_SUCCESS - } + + + +sail(): | + { + let rs1_val_S = F_or_X_S(rs1); + let rs2_val_S = F_or_X_S(rs2); + let (fflags, rd_val) : (bits_fflags, bool) = + riscv_f32Le (rs1_val_S, rs2_val_S); + accrue_fflags(fflags); + X(rd) = zero_extend(bool_to_bits(rd_val)); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fmaxm.s.yaml b/arch/inst/F/fmaxm.s.yaml index fb1306aa9..b303bdfdd 100644 --- a/arch/inst/F/fmaxm.s.yaml +++ b/arch/inst/F/fmaxm.s.yaml @@ -1,50 +1,52 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmaxm.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F, Zfa - assembly: xd, xs1, xs2 - encoding: - match: 0010100----------011-----1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_S = F_S(rs1); - let rs2_val_S = F_S(rs2); +$schema: "inst_schema.json#" +kind: instruction +name: fmaxm.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F, Zfa +assembly: xd, xs1, xs2 +encoding: + match: 0010100----------011-----1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - let is_quiet = true; - let (rs2_lt_rs1, fflags) = fle_S (rs2_val_S, rs1_val_S, is_quiet); - - let rd_val_S = if (f_is_NaN_S(rs1_val_S) | f_is_NaN_S(rs2_val_S)) then canonical_NaN_S() - else if (f_is_neg_zero_S(rs1_val_S) & f_is_pos_zero_S(rs2_val_S)) then rs2_val_S - else if (f_is_neg_zero_S(rs2_val_S) & f_is_pos_zero_S(rs1_val_S)) then rs1_val_S - else if rs2_lt_rs1 then rs1_val_S - else /* (not rs2_lt_rs1) */ rs2_val_S; - - accrue_fflags(fflags); - F_S(rd) = rd_val_S; - RETIRE_SUCCESS - } + + + +sail(): | + { + let rs1_val_S = F_S(rs1); + let rs2_val_S = F_S(rs2); + + let is_quiet = true; + let (rs2_lt_rs1, fflags) = fle_S (rs2_val_S, rs1_val_S, is_quiet); + let rd_val_S = if (f_is_NaN_S(rs1_val_S) | f_is_NaN_S(rs2_val_S)) then canonical_NaN_S() + else if (f_is_neg_zero_S(rs1_val_S) & f_is_pos_zero_S(rs2_val_S)) then rs2_val_S + else if (f_is_neg_zero_S(rs2_val_S) & f_is_pos_zero_S(rs1_val_S)) then rs1_val_S + else if rs2_lt_rs1 then rs1_val_S + else /* (not rs2_lt_rs1) */ rs2_val_S; + accrue_fflags(fflags); + F_S(rd) = rd_val_S; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fmin.s.yaml b/arch/inst/F/fmin.s.yaml index ee99b07cc..667ddee84 100644 --- a/arch/inst/F/fmin.s.yaml +++ b/arch/inst/F/fmin.s.yaml @@ -1,44 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmin.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - assembly: xd, xs1, xs2 - encoding: - match: 0010100----------000-----1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_S = F_or_X_S(rs1); - let rs2_val_S = F_or_X_S(rs2); +$schema: "inst_schema.json#" +kind: instruction +name: fmin.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +assembly: xd, xs1, xs2 +encoding: + match: 0010100----------000-----1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - let (fflags, rd_val) : (bits_fflags, bool) = - riscv_f32Le (rs1_val_S, rs2_val_S); - - accrue_fflags(fflags); - X(rd) = zero_extend(bool_to_bits(rd_val)); - RETIRE_SUCCESS - } + + + +sail(): | + { + let rs1_val_S = F_or_X_S(rs1); + let rs2_val_S = F_or_X_S(rs2); + let (fflags, rd_val) : (bits_fflags, bool) = + riscv_f32Le (rs1_val_S, rs2_val_S); + accrue_fflags(fflags); + X(rd) = zero_extend(bool_to_bits(rd_val)); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fminm.s.yaml b/arch/inst/F/fminm.s.yaml index 654cd126c..83b6cf7bf 100644 --- a/arch/inst/F/fminm.s.yaml +++ b/arch/inst/F/fminm.s.yaml @@ -1,50 +1,52 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fminm.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F, Zfa - assembly: fd, fs1, fs2 - encoding: - match: 0010100----------010-----1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_S = F_S(rs1); - let rs2_val_S = F_S(rs2); +$schema: "inst_schema.json#" +kind: instruction +name: fminm.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F, Zfa +assembly: fd, fs1, fs2 +encoding: + match: 0010100----------010-----1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - let is_quiet = true; - let (rs1_lt_rs2, fflags) = fle_S (rs1_val_S, rs2_val_S, is_quiet); - - let rd_val_S = if (f_is_NaN_S(rs1_val_S) | f_is_NaN_S(rs2_val_S)) then canonical_NaN_S() - else if (f_is_neg_zero_S(rs1_val_S) & f_is_pos_zero_S(rs2_val_S)) then rs1_val_S - else if (f_is_neg_zero_S(rs2_val_S) & f_is_pos_zero_S(rs1_val_S)) then rs2_val_S - else if rs1_lt_rs2 then rs1_val_S - else /* (not rs1_lt_rs2) */ rs2_val_S; - - accrue_fflags(fflags); - F_S(rd) = rd_val_S; - RETIRE_SUCCESS - } + + + +sail(): | + { + let rs1_val_S = F_S(rs1); + let rs2_val_S = F_S(rs2); + + let is_quiet = true; + let (rs1_lt_rs2, fflags) = fle_S (rs1_val_S, rs2_val_S, is_quiet); + let rd_val_S = if (f_is_NaN_S(rs1_val_S) | f_is_NaN_S(rs2_val_S)) then canonical_NaN_S() + else if (f_is_neg_zero_S(rs1_val_S) & f_is_pos_zero_S(rs2_val_S)) then rs1_val_S + else if (f_is_neg_zero_S(rs2_val_S) & f_is_pos_zero_S(rs1_val_S)) then rs2_val_S + else if rs1_lt_rs2 then rs1_val_S + else /* (not rs1_lt_rs2) */ rs2_val_S; + accrue_fflags(fflags); + F_S(rd) = rd_val_S; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fmsub.s.yaml b/arch/inst/F/fmsub.s.yaml index b8273c830..b12a96acd 100644 --- a/arch/inst/F/fmsub.s.yaml +++ b/arch/inst/F/fmsub.s.yaml @@ -1,58 +1,60 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmsub.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - assembly: fd, fs1, fs2, fs3, rm - encoding: - match: -----00------------------1000111 - variables: - - name: fs3 - location: 31-27 - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_32b = F_or_X_S(rs1); - let rs2_val_32b = F_or_X_S(rs2); - let rs3_val_32b = F_or_X_S(rs3); - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_32b) : (bits(5), bits(32)) = - match op { - FMADD_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, rs3_val_32b), - FMSUB_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, negate_S (rs3_val_32b)), - FNMSUB_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, rs3_val_32b), - FNMADD_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, negate_S (rs3_val_32b)) - }; - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_32b; - RETIRE_SUCCESS - } +$schema: "inst_schema.json#" +kind: instruction +name: fmsub.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +assembly: fd, fs1, fs2, fs3, rm +encoding: + match: -----00------------------1000111 + variables: + - name: fs3 + location: 31-27 + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + + + + +sail(): | + { + let rs1_val_32b = F_or_X_S(rs1); + let rs2_val_32b = F_or_X_S(rs2); + let rs3_val_32b = F_or_X_S(rs3); + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_32b) : (bits(5), bits(32)) = + match op { + FMADD_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, rs3_val_32b), + FMSUB_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, negate_S (rs3_val_32b)), + FNMSUB_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, rs3_val_32b), + FNMADD_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, negate_S (rs3_val_32b)) + }; + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_32b; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fmul.s.yaml b/arch/inst/F/fmul.s.yaml index 351349e4e..c374137a1 100644 --- a/arch/inst/F/fmul.s.yaml +++ b/arch/inst/F/fmul.s.yaml @@ -1,54 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmul.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - assembly: fd, fs1, fs2, rm - encoding: - match: 0001000------------------1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_32b = F_or_X_S(rs1); - let rs2_val_32b = F_or_X_S(rs2); - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_32b) : (bits(5), bits(32)) = match op { - FADD_S => riscv_f32Add (rm_3b, rs1_val_32b, rs2_val_32b), - FSUB_S => riscv_f32Sub (rm_3b, rs1_val_32b, rs2_val_32b), - FMUL_S => riscv_f32Mul (rm_3b, rs1_val_32b, rs2_val_32b), - FDIV_S => riscv_f32Div (rm_3b, rs1_val_32b, rs2_val_32b) - }; - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_32b; - RETIRE_SUCCESS - } +$schema: "inst_schema.json#" +kind: instruction +name: fmul.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +assembly: fd, fs1, fs2, rm +encoding: + match: 0001000------------------1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + + + + +sail(): | + { + let rs1_val_32b = F_or_X_S(rs1); + let rs2_val_32b = F_or_X_S(rs2); + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_32b) : (bits(5), bits(32)) = match op { + FADD_S => riscv_f32Add (rm_3b, rs1_val_32b, rs2_val_32b), + FSUB_S => riscv_f32Sub (rm_3b, rs1_val_32b, rs2_val_32b), + FMUL_S => riscv_f32Mul (rm_3b, rs1_val_32b, rs2_val_32b), + FDIV_S => riscv_f32Div (rm_3b, rs1_val_32b, rs2_val_32b) + }; + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_32b; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fmv.w.x.yaml b/arch/inst/F/fmv.w.x.yaml index 2fe7e02b0..e65476f9a 100644 --- a/arch/inst/F/fmv.w.x.yaml +++ b/arch/inst/F/fmv.w.x.yaml @@ -1,50 +1,52 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmv.w.x: - long_name: Single-precision floating-point move from integer - description: | - Moves the single-precision value encoded in IEEE 754-2008 standard encoding - from the lower 32 bits of integer register `rs1` to the floating-point - register `fd`. The bits are not modified in the transfer, and in particular, - the payloads of non-canonical NaNs are preserved. - definedBy: F - assembly: fd, xs1 - encoding: - match: 111100000000-----000-----1010011 - variables: - - name: rs1 - location: 19-15 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - check_f_ok($encoding); - - Bits<32> sp_value = X[rs1][31:0]; - - if (implemented?(ExtensionName::D)) { - f[fd] = nan_box<32, 64>(sp_value); - } else { - f[fd] = sp_value; - } - - mark_f_state_dirty(); - - - - sail(): | - { - let rs1_val_X = X(rs1); - let rd_val_S = rs1_val_X [31..0]; - F(rd) = nan_box (rd_val_S); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: fmv.w.x +long_name: Single-precision floating-point move from integer +description: | + Moves the single-precision value encoded in IEEE 754-2008 standard encoding + from the lower 32 bits of integer register `rs1` to the floating-point + register `fd`. The bits are not modified in the transfer, and in particular, + the payloads of non-canonical NaNs are preserved. +definedBy: F +assembly: fd, xs1 +encoding: + match: 111100000000-----000-----1010011 + variables: + - name: rs1 + location: 19-15 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + check_f_ok($encoding); + + Bits<32> sp_value = X[rs1][31:0]; + + if (implemented?(ExtensionName::D)) { + f[fd] = nan_box<32, 64>(sp_value); + } else { + f[fd] = sp_value; + } + + mark_f_state_dirty(); + + + +sail(): | + { + let rs1_val_X = X(rs1); + let rd_val_S = rs1_val_X [31..0]; + F(rd) = nan_box (rd_val_S); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fmv.x.w.yaml b/arch/inst/F/fmv.x.w.yaml index 70e4e6dae..baf798a9a 100644 --- a/arch/inst/F/fmv.x.w.yaml +++ b/arch/inst/F/fmv.x.w.yaml @@ -1,44 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmv.x.w: - long_name: Move single-precision value from floating-point to integer register - description: | - Moves the single-precision value in floating-point register rs1 represented in IEEE 754-2008 - encoding to the lower 32 bits of integer register rd. - The bits are not modified in the transfer, and in particular, the payloads of non-canonical - NaNs are preserved. - For RV64, the higher 32 bits of the destination register are filled with copies of the - floating-point number's sign bit. - definedBy: F - assembly: xd, fs1 - encoding: - match: 111000000000-----000-----1010011 - variables: - - name: fs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - check_f_ok($encoding); - - X[rd] = sext(f[fs1][31:0], 32); - - - - sail(): | - { - let rs1_val_X = X(rs1); - let rd_val_S = rs1_val_X [31..0]; - F(rd) = nan_box (rd_val_S); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: fmv.x.w +long_name: Move single-precision value from floating-point to integer register +description: | + Moves the single-precision value in floating-point register rs1 represented in IEEE 754-2008 + encoding to the lower 32 bits of integer register rd. + The bits are not modified in the transfer, and in particular, the payloads of non-canonical + NaNs are preserved. + For RV64, the higher 32 bits of the destination register are filled with copies of the + floating-point number's sign bit. +definedBy: F +assembly: xd, fs1 +encoding: + match: 111000000000-----000-----1010011 + variables: + - name: fs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + check_f_ok($encoding); + + X[rd] = sext(f[fs1][31:0], 32); + + + +sail(): | + { + let rs1_val_X = X(rs1); + let rd_val_S = rs1_val_X [31..0]; + F(rd) = nan_box (rd_val_S); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fnmadd.s.yaml b/arch/inst/F/fnmadd.s.yaml index b18f52274..6d6675003 100644 --- a/arch/inst/F/fnmadd.s.yaml +++ b/arch/inst/F/fnmadd.s.yaml @@ -1,58 +1,60 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fnmadd.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - assembly: fd, fs1, fs2, fs3, rm - encoding: - match: -----00------------------1001111 - variables: - - name: fs3 - location: 31-27 - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_32b = F_or_X_S(rs1); - let rs2_val_32b = F_or_X_S(rs2); - let rs3_val_32b = F_or_X_S(rs3); - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_32b) : (bits(5), bits(32)) = - match op { - FMADD_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, rs3_val_32b), - FMSUB_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, negate_S (rs3_val_32b)), - FNMSUB_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, rs3_val_32b), - FNMADD_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, negate_S (rs3_val_32b)) - }; - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_32b; - RETIRE_SUCCESS - } +$schema: "inst_schema.json#" +kind: instruction +name: fnmadd.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +assembly: fd, fs1, fs2, fs3, rm +encoding: + match: -----00------------------1001111 + variables: + - name: fs3 + location: 31-27 + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + + + + +sail(): | + { + let rs1_val_32b = F_or_X_S(rs1); + let rs2_val_32b = F_or_X_S(rs2); + let rs3_val_32b = F_or_X_S(rs3); + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_32b) : (bits(5), bits(32)) = + match op { + FMADD_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, rs3_val_32b), + FMSUB_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, negate_S (rs3_val_32b)), + FNMSUB_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, rs3_val_32b), + FNMADD_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, negate_S (rs3_val_32b)) + }; + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_32b; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fnmsub.s.yaml b/arch/inst/F/fnmsub.s.yaml index c79919e0c..61bfb97d1 100644 --- a/arch/inst/F/fnmsub.s.yaml +++ b/arch/inst/F/fnmsub.s.yaml @@ -1,58 +1,60 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fnmsub.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - assembly: xd, xs1, xs2, xs3, rm - encoding: - match: -----00------------------1001011 - variables: - - name: fs3 - location: 31-27 - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_32b = F_or_X_S(rs1); - let rs2_val_32b = F_or_X_S(rs2); - let rs3_val_32b = F_or_X_S(rs3); - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_32b) : (bits(5), bits(32)) = - match op { - FMADD_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, rs3_val_32b), - FMSUB_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, negate_S (rs3_val_32b)), - FNMSUB_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, rs3_val_32b), - FNMADD_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, negate_S (rs3_val_32b)) - }; - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_32b; - RETIRE_SUCCESS - } +$schema: "inst_schema.json#" +kind: instruction +name: fnmsub.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +assembly: xd, xs1, xs2, xs3, rm +encoding: + match: -----00------------------1001011 + variables: + - name: fs3 + location: 31-27 + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + + + + +sail(): | + { + let rs1_val_32b = F_or_X_S(rs1); + let rs2_val_32b = F_or_X_S(rs2); + let rs3_val_32b = F_or_X_S(rs3); + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_32b) : (bits(5), bits(32)) = + match op { + FMADD_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, rs3_val_32b), + FMSUB_S => riscv_f32MulAdd (rm_3b, rs1_val_32b, rs2_val_32b, negate_S (rs3_val_32b)), + FNMSUB_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, rs3_val_32b), + FNMADD_S => riscv_f32MulAdd (rm_3b, negate_S (rs1_val_32b), rs2_val_32b, negate_S (rs3_val_32b)) + }; + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_32b; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fround.s.yaml b/arch/inst/F/fround.s.yaml index 1abaee7cf..cd57704a9 100644 --- a/arch/inst/F/fround.s.yaml +++ b/arch/inst/F/fround.s.yaml @@ -1,48 +1,50 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fround.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F, Zfa - assembly: fd, xs1, rm - encoding: - match: 010000000100-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_S = F_S(rs1); +$schema: "inst_schema.json#" +kind: instruction +name: fround.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F, Zfa +assembly: fd, xs1, rm +encoding: + match: 010000000100-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - match (select_instr_or_fcsr_rm(rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_S) = riscv_f32roundToInt(rm_3b, rs1_val_S, false); - - accrue_fflags(fflags); - F_S(rd) = rd_val_S; - RETIRE_SUCCESS - } - } - } + + + +sail(): | + { + let rs1_val_S = F_S(rs1); + match (select_instr_or_fcsr_rm(rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_S) = riscv_f32roundToInt(rm_3b, rs1_val_S, false); + accrue_fflags(fflags); + F_S(rd) = rd_val_S; + RETIRE_SUCCESS + } + } + } + + diff --git a/arch/inst/F/froundnx.s.yaml b/arch/inst/F/froundnx.s.yaml index e2ff58391..828dfd8b6 100644 --- a/arch/inst/F/froundnx.s.yaml +++ b/arch/inst/F/froundnx.s.yaml @@ -1,48 +1,50 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -froundnx.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F, Zfa - assembly: fd, rs1, rm - encoding: - match: 010000000101-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_S = F_S(rs1); +$schema: "inst_schema.json#" +kind: instruction +name: froundnx.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F, Zfa +assembly: fd, rs1, rm +encoding: + match: 010000000101-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - match (select_instr_or_fcsr_rm(rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_S) = riscv_f32roundToInt(rm_3b, rs1_val_S, true); - - accrue_fflags(fflags); - F_S(rd) = rd_val_S; - RETIRE_SUCCESS - } - } - } + + + +sail(): | + { + let rs1_val_S = F_S(rs1); + match (select_instr_or_fcsr_rm(rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_S) = riscv_f32roundToInt(rm_3b, rs1_val_S, true); + accrue_fflags(fflags); + F_S(rd) = rd_val_S; + RETIRE_SUCCESS + } + } + } + + diff --git a/arch/inst/F/fsgnj.s.yaml b/arch/inst/F/fsgnj.s.yaml index 2e18fada4..46e49f2a0 100644 --- a/arch/inst/F/fsgnj.s.yaml +++ b/arch/inst/F/fsgnj.s.yaml @@ -1,61 +1,63 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fsgnj.s: - long_name: Single-precision sign inject - description: | - Writes _fd_ with sign bit of _fs2_ and the exponent and mantissa of _fs1_. - - Sign-injection instructions do not set floating-point exception flags, nor do they canonicalize NaNs. - - definedBy: F - assembly: fd, fs1, fs2 - encoding: - match: 0010000----------000-----1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - pseudoinstructions: - - when: (rs2 == rs1) - to: fmv.s - - operation(): | - check_f_ok($encoding); - - Bits<32> sp_value = {f[fs2][31], f[fs1][30:0]}; - - if (implemented?(ExtensionName::D)) { - f[fd] = nan_box<32, 64>(sp_value); - } else { - f[fd] = sp_value; - } - - mark_f_state_dirty(); - - - - sail(): | - { - let rs1_val_S = F_or_X_S(rs1); - let rs2_val_S = F_or_X_S(rs2); - - let (fflags, rd_val) : (bits_fflags, bool) = - riscv_f32Le (rs1_val_S, rs2_val_S); - - accrue_fflags(fflags); - X(rd) = zero_extend(bool_to_bits(rd_val)); - RETIRE_SUCCESS - } +$schema: "inst_schema.json#" +kind: instruction +name: fsgnj.s +long_name: Single-precision sign inject +description: | + Writes _fd_ with sign bit of _fs2_ and the exponent and mantissa of _fs1_. + + Sign-injection instructions do not set floating-point exception flags, nor do they canonicalize NaNs. + +definedBy: F +assembly: fd, fs1, fs2 +encoding: + match: 0010000----------000-----1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +pseudoinstructions: +- when: (rs2 == rs1) + to: fmv.s + +operation(): | + check_f_ok($encoding); + + Bits<32> sp_value = {f[fs2][31], f[fs1][30:0]}; + + if (implemented?(ExtensionName::D)) { + f[fd] = nan_box<32, 64>(sp_value); + } else { + f[fd] = sp_value; + } + + mark_f_state_dirty(); + + + +sail(): | + { + let rs1_val_S = F_or_X_S(rs1); + let rs2_val_S = F_or_X_S(rs2); + let (fflags, rd_val) : (bits_fflags, bool) = + riscv_f32Le (rs1_val_S, rs2_val_S); + accrue_fflags(fflags); + X(rd) = zero_extend(bool_to_bits(rd_val)); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fsgnjn.s.yaml b/arch/inst/F/fsgnjn.s.yaml index e9d9fee17..a6b927efa 100644 --- a/arch/inst/F/fsgnjn.s.yaml +++ b/arch/inst/F/fsgnjn.s.yaml @@ -1,60 +1,62 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fsgnjn.s: - long_name: Single-precision sign inject negate - description: | - Writes _fd_ with the opposite of the sign bit of _fs2_ and the exponent and mantissa of _fs1_. - - Sign-injection instructions do not set floating-point exception flags, nor do they canonicalize NaNs. - definedBy: F - assembly: fd, fs1, fs2 - encoding: - match: 0010000----------001-----1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - pseudoinstructions: - - when: (rs2 == rs1) - to: fneg.s - - operation(): | - check_f_ok($encoding); - - Bits<32> sp_value = {~f[fs2][31], f[fs1][30:0]}; - - if (implemented?(ExtensionName::D)) { - f[fd] = nan_box<32, 64>(sp_value); - } else { - f[fd] = sp_value; - } - - mark_f_state_dirty(); - - - - sail(): | - { - let rs1_val_S = F_or_X_S(rs1); - let rs2_val_S = F_or_X_S(rs2); - - let (fflags, rd_val) : (bits_fflags, bool) = - riscv_f32Le (rs1_val_S, rs2_val_S); - - accrue_fflags(fflags); - X(rd) = zero_extend(bool_to_bits(rd_val)); - RETIRE_SUCCESS - } +$schema: "inst_schema.json#" +kind: instruction +name: fsgnjn.s +long_name: Single-precision sign inject negate +description: | + Writes _fd_ with the opposite of the sign bit of _fs2_ and the exponent and mantissa of _fs1_. + + Sign-injection instructions do not set floating-point exception flags, nor do they canonicalize NaNs. +definedBy: F +assembly: fd, fs1, fs2 +encoding: + match: 0010000----------001-----1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +pseudoinstructions: +- when: (rs2 == rs1) + to: fneg.s + +operation(): | + check_f_ok($encoding); + + Bits<32> sp_value = {~f[fs2][31], f[fs1][30:0]}; + + if (implemented?(ExtensionName::D)) { + f[fd] = nan_box<32, 64>(sp_value); + } else { + f[fd] = sp_value; + } + + mark_f_state_dirty(); + + + +sail(): | + { + let rs1_val_S = F_or_X_S(rs1); + let rs2_val_S = F_or_X_S(rs2); + let (fflags, rd_val) : (bits_fflags, bool) = + riscv_f32Le (rs1_val_S, rs2_val_S); + accrue_fflags(fflags); + X(rd) = zero_extend(bool_to_bits(rd_val)); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fsgnjx.s.yaml b/arch/inst/F/fsgnjx.s.yaml index b10b77967..720e88e6f 100644 --- a/arch/inst/F/fsgnjx.s.yaml +++ b/arch/inst/F/fsgnjx.s.yaml @@ -1,59 +1,61 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fsgnjx.s: - long_name: Single-precision sign inject exclusive or - description: | - Writes _fd_ with the xor of the sign bits of _fs2_ and _fs1_ and the exponent and mantissa of _fs1_. - - Sign-injection instructions do not set floating-point exception flags, nor do they canonicalize NaNs. - definedBy: F - assembly: fd, fs1, fs2 - encoding: - match: 0010000----------010-----1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - pseudoinstructions: - - when: (rs2 == rs1) - to: fabs.s - operation(): | - check_f_ok($encoding); - - Bits<32> sp_value = {f[fs1][31] ^ f[fs2][31], f[fs1][30:0]}; - - if (implemented?(ExtensionName::D)) { - f[fd] = nan_box<32, 64>(sp_value); - } else { - f[fd] = sp_value; - } - - mark_f_state_dirty(); - - - - sail(): | - { - let rs1_val_S = F_or_X_S(rs1); - let rs2_val_S = F_or_X_S(rs2); - - let (fflags, rd_val) : (bits_fflags, bool) = - riscv_f32Le (rs1_val_S, rs2_val_S); - - accrue_fflags(fflags); - X(rd) = zero_extend(bool_to_bits(rd_val)); - RETIRE_SUCCESS - } +$schema: "inst_schema.json#" +kind: instruction +name: fsgnjx.s +long_name: Single-precision sign inject exclusive or +description: | + Writes _fd_ with the xor of the sign bits of _fs2_ and _fs1_ and the exponent and mantissa of _fs1_. + + Sign-injection instructions do not set floating-point exception flags, nor do they canonicalize NaNs. +definedBy: F +assembly: fd, fs1, fs2 +encoding: + match: 0010000----------010-----1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +pseudoinstructions: +- when: (rs2 == rs1) + to: fabs.s +operation(): | + check_f_ok($encoding); + + Bits<32> sp_value = {f[fs1][31] ^ f[fs2][31], f[fs1][30:0]}; + + if (implemented?(ExtensionName::D)) { + f[fd] = nan_box<32, 64>(sp_value); + } else { + f[fd] = sp_value; + } + + mark_f_state_dirty(); + + + +sail(): | + { + let rs1_val_S = F_or_X_S(rs1); + let rs2_val_S = F_or_X_S(rs2); + let (fflags, rd_val) : (bits_fflags, bool) = + riscv_f32Le (rs1_val_S, rs2_val_S); + accrue_fflags(fflags); + X(rd) = zero_extend(bool_to_bits(rd_val)); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/F/fsqrt.s.yaml b/arch/inst/F/fsqrt.s.yaml index 7bbf5f9f8..5a4c708c6 100644 --- a/arch/inst/F/fsqrt.s.yaml +++ b/arch/inst/F/fsqrt.s.yaml @@ -1,48 +1,50 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fsqrt.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - assembly: fd, fs1, rm - encoding: - match: 010110000000-------------1010011 - variables: - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - assert(sizeof(xlen) >= 64); - let rs1_val_LU = X(rs1)[63..0]; - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); +$schema: "inst_schema.json#" +kind: instruction +name: fsqrt.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +assembly: fd, fs1, rm +encoding: + match: 010110000000-------------1010011 + variables: + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_S; - RETIRE_SUCCESS - } + + + +sail(): | + { + assert(sizeof(xlen) >= 64); + let rs1_val_LU = X(rs1)[63..0]; + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_S) = riscv_ui64ToF32 (rm_3b, rs1_val_LU); + + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_S; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fsub.s.yaml b/arch/inst/F/fsub.s.yaml index 3f8787686..7a2382675 100644 --- a/arch/inst/F/fsub.s.yaml +++ b/arch/inst/F/fsub.s.yaml @@ -1,54 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fsub.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: F - assembly: fd, fs1, fs2, rm - encoding: - match: 0000100------------------1010011 - variables: - - name: fs2 - location: 24-20 - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - - - - - sail(): | - { - let rs1_val_32b = F_or_X_S(rs1); - let rs2_val_32b = F_or_X_S(rs2); - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_32b) : (bits(5), bits(32)) = match op { - FADD_S => riscv_f32Add (rm_3b, rs1_val_32b, rs2_val_32b), - FSUB_S => riscv_f32Sub (rm_3b, rs1_val_32b, rs2_val_32b), - FMUL_S => riscv_f32Mul (rm_3b, rs1_val_32b, rs2_val_32b), - FDIV_S => riscv_f32Div (rm_3b, rs1_val_32b, rs2_val_32b) - }; - accrue_fflags(fflags); - F_or_X_S(rd) = rd_val_32b; - RETIRE_SUCCESS - } +$schema: "inst_schema.json#" +kind: instruction +name: fsub.s +long_name: No synopsis available. +description: | + No description available. +definedBy: F +assembly: fd, fs1, fs2, rm +encoding: + match: 0000100------------------1010011 + variables: + - name: fs2 + location: 24-20 + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + + + + +sail(): | + { + let rs1_val_32b = F_or_X_S(rs1); + let rs2_val_32b = F_or_X_S(rs2); + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_32b) : (bits(5), bits(32)) = match op { + FADD_S => riscv_f32Add (rm_3b, rs1_val_32b, rs2_val_32b), + FSUB_S => riscv_f32Sub (rm_3b, rs1_val_32b, rs2_val_32b), + FMUL_S => riscv_f32Mul (rm_3b, rs1_val_32b, rs2_val_32b), + FDIV_S => riscv_f32Div (rm_3b, rs1_val_32b, rs2_val_32b) + }; + accrue_fflags(fflags); + F_or_X_S(rd) = rd_val_32b; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/F/fsw.yaml b/arch/inst/F/fsw.yaml index f24c2ab7e..047d045ad 100644 --- a/arch/inst/F/fsw.yaml +++ b/arch/inst/F/fsw.yaml @@ -1,77 +1,79 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fsw: - long_name: Single-precision floating-point store - description: | - The `fsw` instruction stores a single-precision floating-point value in _fs2_ to memory at address _rs1_ + _imm_. +$schema: "inst_schema.json#" +kind: instruction +name: fsw +long_name: Single-precision floating-point store +description: | + The `fsw` instruction stores a single-precision floating-point value in _fs2_ to memory at address _rs1_ + _imm_. - `fsw` does not modify the bits being transferred; in particular, the payloads of non-canonical NaNs are preserved. + `fsw` does not modify the bits being transferred; in particular, the payloads of non-canonical NaNs are preserved. - definedBy: F - assembly: fs2, xs1, imm - encoding: - match: -----------------010-----0100111 - variables: - - name: imm - location: 31-25|11-7 - - name: fs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - check_f_ok($encoding); +definedBy: F +assembly: fs2, xs1, imm +encoding: + match: -----------------010-----0100111 + variables: + - name: imm + location: 31-25|11-7 + - name: fs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + check_f_ok($encoding); - XReg virtual_address = X[rs1] + $signed(imm); + XReg virtual_address = X[rs1] + $signed(imm); - write_memory<32>(virtual_address, f[fs2][31:0], $encoding); + write_memory<32>(virtual_address, f[fs2][31:0], $encoding); - sail(): | - { - let offset : xlenbits = sign_extend(imm); - let (aq, rl, con) = (false, false, false); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Write(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Write(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match width { - BYTE => MemValue () /* bogus placeholder for illegal size */, - HALF => mem_write_ea(addr, 2, aq, rl, false), - WORD => mem_write_ea(addr, 4, aq, rl, false), - DOUBLE => mem_write_ea(addr, 8, aq, rl, false) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let rs2_val = F(rs2); - match (width) { - BYTE => { handle_illegal(); RETIRE_FAIL }, - HALF => process_fstore (vaddr, mem_write_value(addr, 2, rs2_val[15..0], aq, rl, con)), - WORD => process_fstore (vaddr, mem_write_value(addr, 4, rs2_val[31..0], aq, rl, con)), - DOUBLE if sizeof(flen) >= 64 => - process_fstore (vaddr, mem_write_value(addr, 8, rs2_val, aq, rl, con)), - _ => report_invalid_width(__FILE__, __LINE__, width, "floating point store"), - }; - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + let (aq, rl, con) = (false, false, false); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Write(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Write(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match width { + BYTE => MemValue () /* bogus placeholder for illegal size */, + HALF => mem_write_ea(addr, 2, aq, rl, false), + WORD => mem_write_ea(addr, 4, aq, rl, false), + DOUBLE => mem_write_ea(addr, 8, aq, rl, false) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let rs2_val = F(rs2); + match (width) { + BYTE => { handle_illegal(); RETIRE_FAIL }, + HALF => process_fstore (vaddr, mem_write_value(addr, 2, rs2_val[15..0], aq, rl, con)), + WORD => process_fstore (vaddr, mem_write_value(addr, 4, rs2_val[31..0], aq, rl, con)), + DOUBLE if sizeof(flen) >= 64 => + process_fstore (vaddr, mem_write_value(addr, 8, rs2_val, aq, rl, con)), + _ => report_invalid_width(__FILE__, __LINE__, width, "floating point store"), + }; } } } - } + } } - - + } + + diff --git a/arch/inst/H/hfence.vvma.yaml b/arch/inst/H/hfence.vvma.yaml index dc55bd96e..d02fa52f8 100644 --- a/arch/inst/H/hfence.vvma.yaml +++ b/arch/inst/H/hfence.vvma.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hfence.vvma: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - assembly: xs1, xs2 - encoding: - match: 0010001----------000000001110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hfence.vvma +long_name: No synopsis available. +description: | + No description available. +definedBy: H +assembly: xs1, xs2 +encoding: + match: 0010001----------000000001110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/H/hlv.b.yaml b/arch/inst/H/hlv.b.yaml index fb6394c7e..f0b586dfc 100644 --- a/arch/inst/H/hlv.b.yaml +++ b/arch/inst/H/hlv.b.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hlv.b: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - assembly: xd, xs1 - encoding: - match: 011000000000-----100-----1110011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hlv.b +long_name: No synopsis available. +description: | + No description available. +definedBy: H +assembly: xd, xs1 +encoding: + match: 011000000000-----100-----1110011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/H/hlv.bu.yaml b/arch/inst/H/hlv.bu.yaml index a7cc212ce..bbc92947e 100644 --- a/arch/inst/H/hlv.bu.yaml +++ b/arch/inst/H/hlv.bu.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hlv.bu: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - assembly: xd, xs1 - encoding: - match: 011000000001-----100-----1110011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hlv.bu +long_name: No synopsis available. +description: | + No description available. +definedBy: H +assembly: xd, xs1 +encoding: + match: 011000000001-----100-----1110011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/H/hlv.d.yaml b/arch/inst/H/hlv.d.yaml index afd324673..1d4e4d9f9 100644 --- a/arch/inst/H/hlv.d.yaml +++ b/arch/inst/H/hlv.d.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hlv.d: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - base: 64 - assembly: xd, xs1 - encoding: - match: 011011000000-----100-----1110011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hlv.d +long_name: No synopsis available. +description: | + No description available. +definedBy: H +base: 64 +assembly: xd, xs1 +encoding: + match: 011011000000-----100-----1110011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/H/hlv.h.yaml b/arch/inst/H/hlv.h.yaml index d0043a0e5..5b0340c16 100644 --- a/arch/inst/H/hlv.h.yaml +++ b/arch/inst/H/hlv.h.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hlv.h: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - assembly: xd, xs1 - encoding: - match: 011001000000-----100-----1110011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hlv.h +long_name: No synopsis available. +description: | + No description available. +definedBy: H +assembly: xd, xs1 +encoding: + match: 011001000000-----100-----1110011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/H/hlv.hu.yaml b/arch/inst/H/hlv.hu.yaml index f06c0131b..29385cf38 100644 --- a/arch/inst/H/hlv.hu.yaml +++ b/arch/inst/H/hlv.hu.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hlv.hu: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - assembly: xd, xs1 - encoding: - match: 011001000001-----100-----1110011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hlv.hu +long_name: No synopsis available. +description: | + No description available. +definedBy: H +assembly: xd, xs1 +encoding: + match: 011001000001-----100-----1110011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/H/hlv.w.yaml b/arch/inst/H/hlv.w.yaml index 0eb6d89ad..96a567e75 100644 --- a/arch/inst/H/hlv.w.yaml +++ b/arch/inst/H/hlv.w.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hlv.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - assembly: xd, xs1 - encoding: - match: 011010000000-----100-----1110011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hlv.w +long_name: No synopsis available. +description: | + No description available. +definedBy: H +assembly: xd, xs1 +encoding: + match: 011010000000-----100-----1110011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/H/hlv.wu.yaml b/arch/inst/H/hlv.wu.yaml index a92224a35..3b7171feb 100644 --- a/arch/inst/H/hlv.wu.yaml +++ b/arch/inst/H/hlv.wu.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hlv.wu: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - base: 64 - assembly: xd, xs1 - encoding: - match: 011010000001-----100-----1110011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hlv.wu +long_name: No synopsis available. +description: | + No description available. +definedBy: H +base: 64 +assembly: xd, xs1 +encoding: + match: 011010000001-----100-----1110011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/H/hlvx.hu.yaml b/arch/inst/H/hlvx.hu.yaml index 0da850ac2..52d7e9c2b 100644 --- a/arch/inst/H/hlvx.hu.yaml +++ b/arch/inst/H/hlvx.hu.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hlvx.hu: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - assembly: xd, xs1 - encoding: - match: 011001000011-----100-----1110011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hlvx.hu +long_name: No synopsis available. +description: | + No description available. +definedBy: H +assembly: xd, xs1 +encoding: + match: 011001000011-----100-----1110011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/H/hlvx.wu.yaml b/arch/inst/H/hlvx.wu.yaml index 10e3373a5..86d744570 100644 --- a/arch/inst/H/hlvx.wu.yaml +++ b/arch/inst/H/hlvx.wu.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hlvx.wu: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - assembly: xd, xs1 - encoding: - match: 011010000011-----100-----1110011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hlvx.wu +long_name: No synopsis available. +description: | + No description available. +definedBy: H +assembly: xd, xs1 +encoding: + match: 011010000011-----100-----1110011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/H/hsv.b.yaml b/arch/inst/H/hsv.b.yaml index ab8cc9046..9cef80e79 100644 --- a/arch/inst/H/hsv.b.yaml +++ b/arch/inst/H/hsv.b.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hsv.b: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - assembly: xs1, xs2 - encoding: - match: 0110001----------100000001110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hsv.b +long_name: No synopsis available. +description: | + No description available. +definedBy: H +assembly: xs1, xs2 +encoding: + match: 0110001----------100000001110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/H/hsv.d.yaml b/arch/inst/H/hsv.d.yaml index 07c81c7f1..350481d93 100644 --- a/arch/inst/H/hsv.d.yaml +++ b/arch/inst/H/hsv.d.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hsv.d: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - base: 64 - assembly: xs1, xs2 - encoding: - match: 0110111----------100000001110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hsv.d +long_name: No synopsis available. +description: | + No description available. +definedBy: H +base: 64 +assembly: xs1, xs2 +encoding: + match: 0110111----------100000001110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/H/hsv.h.yaml b/arch/inst/H/hsv.h.yaml index d537ac2db..b782a4cb5 100644 --- a/arch/inst/H/hsv.h.yaml +++ b/arch/inst/H/hsv.h.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hsv.h: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - assembly: xs1, xs2 - encoding: - match: 0110011----------100000001110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hsv.h +long_name: No synopsis available. +description: | + No description available. +definedBy: H +assembly: xs1, xs2 +encoding: + match: 0110011----------100000001110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/H/hsv.w.yaml b/arch/inst/H/hsv.w.yaml index 9fb56320f..d78fa81bf 100644 --- a/arch/inst/H/hsv.w.yaml +++ b/arch/inst/H/hsv.w.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hsv.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: H - assembly: xs1, xs2 - encoding: - match: 0110101----------100000001110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: hsv.w +long_name: No synopsis available. +description: | + No description available. +definedBy: H +assembly: xs1, xs2 +encoding: + match: 0110101----------100000001110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/I/add.yaml b/arch/inst/I/add.yaml index bfd038c41..83706ffdb 100644 --- a/arch/inst/I/add.yaml +++ b/arch/inst/I/add.yaml @@ -1,57 +1,59 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -add: - long_name: Integer add - description: | - Add the value in rs1 to rs2, and store the result in rd. - Any overflow is thrown away. - definedBy: I - assembly: xd, xs1, xs2 - encoding: - match: 0000000----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): X[rd] = X[rs1] + X[rs2]; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: add +long_name: Integer add +description: | + Add the value in rs1 to rs2, and store the result in rd. + Any overflow is thrown away. +definedBy: I +assembly: xd, xs1, xs2 +encoding: + match: 0000000----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): X[rd] = X[rs1] + X[rs2]; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/addi.yaml b/arch/inst/I/addi.yaml index 5c105c3a1..05db65005 100644 --- a/arch/inst/I/addi.yaml +++ b/arch/inst/I/addi.yaml @@ -1,45 +1,47 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -addi: - long_name: Add immediate - description: Add an immediate to the value in rs1, and store the result in rd - definedBy: I - assembly: xd, xs1, imm - encoding: - match: -----------------000-----0010011 - variables: - - name: imm - $inherits: ../../common/inst_variable_types.yaml#/itype_imm - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): X[rd] = X[rs1] + imm; - - - - sail(): | - { - let rs1_val = X(rs1); - let immext : xlenbits = sign_extend(imm); - let result : xlenbits = match op { - RISCV_ADDI => rs1_val + immext, - RISCV_SLTI => zero_extend(bool_to_bits(rs1_val <_s immext)), - RISCV_SLTIU => zero_extend(bool_to_bits(rs1_val <_u immext)), - RISCV_ANDI => rs1_val & immext, - RISCV_ORI => rs1_val | immext, - RISCV_XORI => rs1_val ^ immext - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: addi +long_name: Add immediate +description: Add an immediate to the value in rs1, and store the result in rd +definedBy: I +assembly: xd, xs1, imm +encoding: + match: -----------------000-----0010011 + variables: + - name: imm + $inherits: common/inst_variable_types.yaml#/itype_imm + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): X[rd] = X[rs1] + imm; + + + +sail(): | + { + let rs1_val = X(rs1); + let immext : xlenbits = sign_extend(imm); + let result : xlenbits = match op { + RISCV_ADDI => rs1_val + immext, + RISCV_SLTI => zero_extend(bool_to_bits(rs1_val <_s immext)), + RISCV_SLTIU => zero_extend(bool_to_bits(rs1_val <_u immext)), + RISCV_ANDI => rs1_val & immext, + RISCV_ORI => rs1_val | immext, + RISCV_XORI => rs1_val ^ immext + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/addiw.yaml b/arch/inst/I/addiw.yaml index 0368a30f2..36f72a725 100644 --- a/arch/inst/I/addiw.yaml +++ b/arch/inst/I/addiw.yaml @@ -1,39 +1,41 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -addiw: - long_name: Add immediate word - description: Add an immediate to the 32-bit value in rs1, and store the sign extended result in rd - definedBy: I - base: 64 - assembly: xd, xs1, imm - encoding: - match: -----------------000-----0011011 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - XReg operand = sext(X[rs1], 31); - X[rd] = sext(operand + imm, 31); - - - - sail(): | - { - let result : xlenbits = sign_extend(imm) + X(rs1); - X(rd) = sign_extend(result[31..0]); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: addiw +long_name: Add immediate word +description: Add an immediate to the 32-bit value in rs1, and store the sign extended result in rd +definedBy: I +base: 64 +assembly: xd, xs1, imm +encoding: + match: -----------------000-----0011011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + XReg operand = sext(X[rs1], 31); + X[rd] = sext(operand + imm, 31); + + + +sail(): | + { + let result : xlenbits = sign_extend(imm) + X(rs1); + X(rd) = sign_extend(result[31..0]); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/addw.yaml b/arch/inst/I/addw.yaml index da260b449..de8262a4e 100644 --- a/arch/inst/I/addw.yaml +++ b/arch/inst/I/addw.yaml @@ -1,50 +1,52 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -addw: - long_name: Add word - description: | - Add the 32-bit values in rs1 to rs2, and store the sign-extended result in rd. - Any overflow is thrown away. - definedBy: I - base: 64 - assembly: xd, xs1, xs2 - encoding: - match: 0000000----------000-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - XReg operand1 = sext(X[rs1], 31); - XReg operand2 = sext(X[rs2], 31); - X[rd] = sext(operand1 + operand2, 31); - - - - sail(): | - { - let rs1_val = (X(rs1))[31..0]; - let rs2_val = (X(rs2))[31..0]; - let result : bits(32) = match op { - RISCV_ADDW => rs1_val + rs2_val, - RISCV_SUBW => rs1_val - rs2_val, - RISCV_SLLW => rs1_val << (rs2_val[4..0]), - RISCV_SRLW => rs1_val >> (rs2_val[4..0]), - RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) - }; - X(rd) = sign_extend(result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: addw +long_name: Add word +description: | + Add the 32-bit values in rs1 to rs2, and store the sign-extended result in rd. + Any overflow is thrown away. +definedBy: I +base: 64 +assembly: xd, xs1, xs2 +encoding: + match: 0000000----------000-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + XReg operand1 = sext(X[rs1], 31); + XReg operand2 = sext(X[rs2], 31); + X[rd] = sext(operand1 + operand2, 31); + + + +sail(): | + { + let rs1_val = (X(rs1))[31..0]; + let rs2_val = (X(rs2))[31..0]; + let result : bits(32) = match op { + RISCV_ADDW => rs1_val + rs2_val, + RISCV_SUBW => rs1_val - rs2_val, + RISCV_SLLW => rs1_val << (rs2_val[4..0]), + RISCV_SRLW => rs1_val >> (rs2_val[4..0]), + RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) + }; + X(rd) = sign_extend(result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/and.yaml b/arch/inst/I/and.yaml index 3f53c135b..815c2cbe6 100644 --- a/arch/inst/I/and.yaml +++ b/arch/inst/I/and.yaml @@ -1,55 +1,57 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -and: - long_name: And - description: And rs1 with rs2, and store the result in rd - definedBy: I - assembly: xd, xs1, xs2 - encoding: - match: 0000000----------111-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): X[rd] = X[rs1] & X[rs2]; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: and +long_name: And +description: And rs1 with rs2, and store the result in rd +definedBy: I +assembly: xd, xs1, xs2 +encoding: + match: 0000000----------111-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): X[rd] = X[rs1] & X[rs2]; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/andi.yaml b/arch/inst/I/andi.yaml index b313d0fc2..9ef488e42 100644 --- a/arch/inst/I/andi.yaml +++ b/arch/inst/I/andi.yaml @@ -1,45 +1,47 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -andi: - long_name: And immediate - description: And an immediate to the value in rs1, and store the result in rd - definedBy: I - assembly: xd, xs1, imm - encoding: - match: -----------------111-----0010011 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): X[rd] = X[rs1] & imm; - - - - sail(): | - { - let rs1_val = X(rs1); - let immext : xlenbits = sign_extend(imm); - let result : xlenbits = match op { - RISCV_ADDI => rs1_val + immext, - RISCV_SLTI => zero_extend(bool_to_bits(rs1_val <_s immext)), - RISCV_SLTIU => zero_extend(bool_to_bits(rs1_val <_u immext)), - RISCV_ANDI => rs1_val & immext, - RISCV_ORI => rs1_val | immext, - RISCV_XORI => rs1_val ^ immext - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: andi +long_name: And immediate +description: And an immediate to the value in rs1, and store the result in rd +definedBy: I +assembly: xd, xs1, imm +encoding: + match: -----------------111-----0010011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): X[rd] = X[rs1] & imm; + + + +sail(): | + { + let rs1_val = X(rs1); + let immext : xlenbits = sign_extend(imm); + let result : xlenbits = match op { + RISCV_ADDI => rs1_val + immext, + RISCV_SLTI => zero_extend(bool_to_bits(rs1_val <_s immext)), + RISCV_SLTIU => zero_extend(bool_to_bits(rs1_val <_u immext)), + RISCV_ANDI => rs1_val & immext, + RISCV_ORI => rs1_val | immext, + RISCV_XORI => rs1_val ^ immext + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/auipc.yaml b/arch/inst/I/auipc.yaml index 9be9fee26..f65fdad53 100644 --- a/arch/inst/I/auipc.yaml +++ b/arch/inst/I/auipc.yaml @@ -1,36 +1,37 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -auipc: - long_name: Add upper immediate to pc - description: Add an immediate to the current PC. - definedBy: I - assembly: xd, imm - encoding: - match: -------------------------0010111 - variables: - - name: imm - location: 31-12 - left_shift: 12 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): X[rd] = $pc + imm; +$schema: "inst_schema.json#" +kind: instruction +name: auipc +long_name: Add upper immediate to pc +description: Add an immediate to the current PC. +definedBy: I +assembly: xd, imm +encoding: + match: -------------------------0010111 + variables: + - name: imm + location: 31-12 + left_shift: 12 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always + data_independent_timing: true +operation(): X[rd] = $pc + imm; - sail(): | - { - let off : xlenbits = sign_extend(imm @ 0x000); - let ret : xlenbits = match op { - RISCV_LUI => off, - RISCV_AUIPC => get_arch_pc() + off - }; - X(rd) = ret; - RETIRE_SUCCESS - } - - \ No newline at end of file +sail(): | + { + let off : xlenbits = sign_extend(imm @ 0x000); + let ret : xlenbits = match op { + RISCV_LUI => off, + RISCV_AUIPC => get_arch_pc() + off + }; + X(rd) = ret; + RETIRE_SUCCESS + } + diff --git a/arch/inst/I/beq.yaml b/arch/inst/I/beq.yaml index e60c670f9..1dde072bf 100644 --- a/arch/inst/I/beq.yaml +++ b/arch/inst/I/beq.yaml @@ -1,71 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -beq: - long_name: Branch if equal - description: | - Branch to PC + imm if - the value in register rs1 is equal to the value in register rs2. +$schema: "inst_schema.json#" +kind: instruction +name: beq +long_name: Branch if equal +description: | + Branch to PC + imm if + the value in register rs1 is equal to the value in register rs2. - Raise a `MisalignedAddress` exception if PC + imm is misaligned. - definedBy: I - assembly: xs1, xs2, imm - encoding: - match: -----------------000-----1100011 - variables: - - name: imm - location: 31|7|30-25|11-8 - left_shift: 1 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg lhs = X[rs1]; - XReg rhs = X[rs2]; + Raise a `MisalignedAddress` exception if PC + imm is misaligned. +definedBy: I +assembly: xs1, xs2, imm +encoding: + match: -----------------000-----1100011 + variables: + - name: imm + location: 31|7|30-25|11-8 + left_shift: 1 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg lhs = X[rs1]; + XReg rhs = X[rs2]; - if (lhs == rhs) { - jump_halfword($pc + imm); - } + if (lhs == rhs) { + jump_halfword($pc + imm); + } - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let taken : bool = match op { - RISCV_BEQ => rs1_val == rs2_val, - RISCV_BNE => rs1_val != rs2_val, - RISCV_BLT => rs1_val <_s rs2_val, - RISCV_BGE => rs1_val >=_s rs2_val, - RISCV_BLTU => rs1_val <_u rs2_val, - RISCV_BGEU => rs1_val >=_u rs2_val - }; - let t : xlenbits = PC + sign_extend(imm); - if taken then { - /* Extensions get the first checks on the prospective target address. */ - match ext_control_check_pc(t) { - Ext_ControlAddr_Error(e) => { - ext_handle_control_check_error(e); - RETIRE_FAIL - }, - Ext_ControlAddr_OK(target) => { - if bit_to_bool(target[1]) & not(extension("C")) then { - handle_mem_exception(target, E_Fetch_Addr_Align()); - RETIRE_FAIL; - } else { - set_next_pc(target); - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let taken : bool = match op { + RISCV_BEQ => rs1_val == rs2_val, + RISCV_BNE => rs1_val != rs2_val, + RISCV_BLT => rs1_val <_s rs2_val, + RISCV_BGE => rs1_val >=_s rs2_val, + RISCV_BLTU => rs1_val <_u rs2_val, + RISCV_BGEU => rs1_val >=_u rs2_val + }; + let t : xlenbits = PC + sign_extend(imm); + if taken then { + /* Extensions get the first checks on the prospective target address. */ + match ext_control_check_pc(t) { + Ext_ControlAddr_Error(e) => { + ext_handle_control_check_error(e); + RETIRE_FAIL + }, + Ext_ControlAddr_OK(target) => { + if bit_to_bool(target[1]) & not(extension("C")) then { + handle_mem_exception(target, E_Fetch_Addr_Align()); + RETIRE_FAIL; + } else { + set_next_pc(target); + RETIRE_SUCCESS } } - } else RETIRE_SUCCESS - } - - + } + } else RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/bge.yaml b/arch/inst/I/bge.yaml index 614a01512..94edce67d 100644 --- a/arch/inst/I/bge.yaml +++ b/arch/inst/I/bge.yaml @@ -1,72 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -bge: - long_name: Branch if greater than or equal - description: | - Branch to PC + imm if - the signed value in register rs1 is greater than or equal to the signed value in register rs2. +$schema: "inst_schema.json#" +kind: instruction +name: bge +long_name: Branch if greater than or equal +description: | + Branch to PC + imm if + the signed value in register rs1 is greater than or equal to the signed value in register rs2. - Raise a `MisalignedAddress` exception if PC + imm is misaligned. - definedBy: I - assembly: xs1, xs2, imm - encoding: - match: -----------------101-----1100011 - variables: - - name: imm - location: 31|7|30-25|11-8 - left_shift: 1 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg lhs = X[rs1]; - XReg rhs = X[rs2]; + Raise a `MisalignedAddress` exception if PC + imm is misaligned. +definedBy: I +assembly: xs1, xs2, imm +encoding: + match: -----------------101-----1100011 + variables: + - name: imm + location: 31|7|30-25|11-8 + left_shift: 1 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg lhs = X[rs1]; + XReg rhs = X[rs2]; - if ($signed(lhs) >= $signed(rhs)) { - jump_halfword($pc + imm); - } - + if ($signed(lhs) >= $signed(rhs)) { + jump_halfword($pc + imm); + } + - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let taken : bool = match op { - RISCV_BEQ => rs1_val == rs2_val, - RISCV_BNE => rs1_val != rs2_val, - RISCV_BLT => rs1_val <_s rs2_val, - RISCV_BGE => rs1_val >=_s rs2_val, - RISCV_BLTU => rs1_val <_u rs2_val, - RISCV_BGEU => rs1_val >=_u rs2_val - }; - let t : xlenbits = PC + sign_extend(imm); - if taken then { - /* Extensions get the first checks on the prospective target address. */ - match ext_control_check_pc(t) { - Ext_ControlAddr_Error(e) => { - ext_handle_control_check_error(e); - RETIRE_FAIL - }, - Ext_ControlAddr_OK(target) => { - if bit_to_bool(target[1]) & not(extension("C")) then { - handle_mem_exception(target, E_Fetch_Addr_Align()); - RETIRE_FAIL; - } else { - set_next_pc(target); - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let taken : bool = match op { + RISCV_BEQ => rs1_val == rs2_val, + RISCV_BNE => rs1_val != rs2_val, + RISCV_BLT => rs1_val <_s rs2_val, + RISCV_BGE => rs1_val >=_s rs2_val, + RISCV_BLTU => rs1_val <_u rs2_val, + RISCV_BGEU => rs1_val >=_u rs2_val + }; + let t : xlenbits = PC + sign_extend(imm); + if taken then { + /* Extensions get the first checks on the prospective target address. */ + match ext_control_check_pc(t) { + Ext_ControlAddr_Error(e) => { + ext_handle_control_check_error(e); + RETIRE_FAIL + }, + Ext_ControlAddr_OK(target) => { + if bit_to_bool(target[1]) & not(extension("C")) then { + handle_mem_exception(target, E_Fetch_Addr_Align()); + RETIRE_FAIL; + } else { + set_next_pc(target); + RETIRE_SUCCESS } } - } else RETIRE_SUCCESS - } - - + } + } else RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/bgeu.yaml b/arch/inst/I/bgeu.yaml index 0eb8d060f..687a65116 100644 --- a/arch/inst/I/bgeu.yaml +++ b/arch/inst/I/bgeu.yaml @@ -1,72 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -bgeu: - long_name: Branch if greater than or equal unsigned - description: | - Branch to PC + imm if - the unsigned value in register rs1 is greater than or equal to the unsigned value in register rs2. +$schema: "inst_schema.json#" +kind: instruction +name: bgeu +long_name: Branch if greater than or equal unsigned +description: | + Branch to PC + imm if + the unsigned value in register rs1 is greater than or equal to the unsigned value in register rs2. - Raise a `MisalignedAddress` exception if PC + imm is misaligned. - definedBy: I - assembly: xs1, xs2, imm - encoding: - match: -----------------111-----1100011 - variables: - - name: imm - location: 31|7|30-25|11-8 - left_shift: 1 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg lhs = X[rs1]; - XReg rhs = X[rs2]; + Raise a `MisalignedAddress` exception if PC + imm is misaligned. +definedBy: I +assembly: xs1, xs2, imm +encoding: + match: -----------------111-----1100011 + variables: + - name: imm + location: 31|7|30-25|11-8 + left_shift: 1 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg lhs = X[rs1]; + XReg rhs = X[rs2]; - if (lhs >= rhs) { - jump_halfword($pc + imm); - } - + if (lhs >= rhs) { + jump_halfword($pc + imm); + } + - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let taken : bool = match op { - RISCV_BEQ => rs1_val == rs2_val, - RISCV_BNE => rs1_val != rs2_val, - RISCV_BLT => rs1_val <_s rs2_val, - RISCV_BGE => rs1_val >=_s rs2_val, - RISCV_BLTU => rs1_val <_u rs2_val, - RISCV_BGEU => rs1_val >=_u rs2_val - }; - let t : xlenbits = PC + sign_extend(imm); - if taken then { - /* Extensions get the first checks on the prospective target address. */ - match ext_control_check_pc(t) { - Ext_ControlAddr_Error(e) => { - ext_handle_control_check_error(e); - RETIRE_FAIL - }, - Ext_ControlAddr_OK(target) => { - if bit_to_bool(target[1]) & not(extension("C")) then { - handle_mem_exception(target, E_Fetch_Addr_Align()); - RETIRE_FAIL; - } else { - set_next_pc(target); - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let taken : bool = match op { + RISCV_BEQ => rs1_val == rs2_val, + RISCV_BNE => rs1_val != rs2_val, + RISCV_BLT => rs1_val <_s rs2_val, + RISCV_BGE => rs1_val >=_s rs2_val, + RISCV_BLTU => rs1_val <_u rs2_val, + RISCV_BGEU => rs1_val >=_u rs2_val + }; + let t : xlenbits = PC + sign_extend(imm); + if taken then { + /* Extensions get the first checks on the prospective target address. */ + match ext_control_check_pc(t) { + Ext_ControlAddr_Error(e) => { + ext_handle_control_check_error(e); + RETIRE_FAIL + }, + Ext_ControlAddr_OK(target) => { + if bit_to_bool(target[1]) & not(extension("C")) then { + handle_mem_exception(target, E_Fetch_Addr_Align()); + RETIRE_FAIL; + } else { + set_next_pc(target); + RETIRE_SUCCESS } } - } else RETIRE_SUCCESS - } - - + } + } else RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/blt.yaml b/arch/inst/I/blt.yaml index 4f40b831d..fca0c0025 100644 --- a/arch/inst/I/blt.yaml +++ b/arch/inst/I/blt.yaml @@ -1,72 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -blt: - long_name: Branch if less than - description: | - Branch to PC + imm if - the signed value in register rs1 is less than the signed value in register rs2. +$schema: "inst_schema.json#" +kind: instruction +name: blt +long_name: Branch if less than +description: | + Branch to PC + imm if + the signed value in register rs1 is less than the signed value in register rs2. - Raise a `MisalignedAddress` exception if PC + imm is misaligned. - definedBy: I - assembly: xs1, xs2, imm - encoding: - match: -----------------100-----1100011 - variables: - - name: imm - location: 31|7|30-25|11-8 - left_shift: 1 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg lhs = X[rs1]; - XReg rhs = X[rs2]; + Raise a `MisalignedAddress` exception if PC + imm is misaligned. +definedBy: I +assembly: xs1, xs2, imm +encoding: + match: -----------------100-----1100011 + variables: + - name: imm + location: 31|7|30-25|11-8 + left_shift: 1 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg lhs = X[rs1]; + XReg rhs = X[rs2]; - if ($signed(lhs) < $signed(rhs)) { - jump_halfword($pc + imm); - } - + if ($signed(lhs) < $signed(rhs)) { + jump_halfword($pc + imm); + } + - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let taken : bool = match op { - RISCV_BEQ => rs1_val == rs2_val, - RISCV_BNE => rs1_val != rs2_val, - RISCV_BLT => rs1_val <_s rs2_val, - RISCV_BGE => rs1_val >=_s rs2_val, - RISCV_BLTU => rs1_val <_u rs2_val, - RISCV_BGEU => rs1_val >=_u rs2_val - }; - let t : xlenbits = PC + sign_extend(imm); - if taken then { - /* Extensions get the first checks on the prospective target address. */ - match ext_control_check_pc(t) { - Ext_ControlAddr_Error(e) => { - ext_handle_control_check_error(e); - RETIRE_FAIL - }, - Ext_ControlAddr_OK(target) => { - if bit_to_bool(target[1]) & not(extension("C")) then { - handle_mem_exception(target, E_Fetch_Addr_Align()); - RETIRE_FAIL; - } else { - set_next_pc(target); - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let taken : bool = match op { + RISCV_BEQ => rs1_val == rs2_val, + RISCV_BNE => rs1_val != rs2_val, + RISCV_BLT => rs1_val <_s rs2_val, + RISCV_BGE => rs1_val >=_s rs2_val, + RISCV_BLTU => rs1_val <_u rs2_val, + RISCV_BGEU => rs1_val >=_u rs2_val + }; + let t : xlenbits = PC + sign_extend(imm); + if taken then { + /* Extensions get the first checks on the prospective target address. */ + match ext_control_check_pc(t) { + Ext_ControlAddr_Error(e) => { + ext_handle_control_check_error(e); + RETIRE_FAIL + }, + Ext_ControlAddr_OK(target) => { + if bit_to_bool(target[1]) & not(extension("C")) then { + handle_mem_exception(target, E_Fetch_Addr_Align()); + RETIRE_FAIL; + } else { + set_next_pc(target); + RETIRE_SUCCESS } } - } else RETIRE_SUCCESS - } - - + } + } else RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/bltu.yaml b/arch/inst/I/bltu.yaml index ceed985fa..919c8cafc 100644 --- a/arch/inst/I/bltu.yaml +++ b/arch/inst/I/bltu.yaml @@ -1,72 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -bltu: - long_name: Branch if less than unsigned - description: | - Branch to PC + imm if - the unsigned value in register rs1 is less than the unsigned value in register rs2. +$schema: "inst_schema.json#" +kind: instruction +name: bltu +long_name: Branch if less than unsigned +description: | + Branch to PC + imm if + the unsigned value in register rs1 is less than the unsigned value in register rs2. - Raise a `MisalignedAddress` exception if PC + imm is misaligned. - definedBy: I - assembly: xs1, xs2, imm - encoding: - match: -----------------110-----1100011 - variables: - - name: imm - location: 31|7|30-25|11-8 - left_shift: 1 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg lhs = X[rs1]; - XReg rhs = X[rs2]; + Raise a `MisalignedAddress` exception if PC + imm is misaligned. +definedBy: I +assembly: xs1, xs2, imm +encoding: + match: -----------------110-----1100011 + variables: + - name: imm + location: 31|7|30-25|11-8 + left_shift: 1 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg lhs = X[rs1]; + XReg rhs = X[rs2]; - if (lhs < rhs) { - jump_halfword($pc + imm); - } - + if (lhs < rhs) { + jump_halfword($pc + imm); + } + - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let taken : bool = match op { - RISCV_BEQ => rs1_val == rs2_val, - RISCV_BNE => rs1_val != rs2_val, - RISCV_BLT => rs1_val <_s rs2_val, - RISCV_BGE => rs1_val >=_s rs2_val, - RISCV_BLTU => rs1_val <_u rs2_val, - RISCV_BGEU => rs1_val >=_u rs2_val - }; - let t : xlenbits = PC + sign_extend(imm); - if taken then { - /* Extensions get the first checks on the prospective target address. */ - match ext_control_check_pc(t) { - Ext_ControlAddr_Error(e) => { - ext_handle_control_check_error(e); - RETIRE_FAIL - }, - Ext_ControlAddr_OK(target) => { - if bit_to_bool(target[1]) & not(extension("C")) then { - handle_mem_exception(target, E_Fetch_Addr_Align()); - RETIRE_FAIL; - } else { - set_next_pc(target); - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let taken : bool = match op { + RISCV_BEQ => rs1_val == rs2_val, + RISCV_BNE => rs1_val != rs2_val, + RISCV_BLT => rs1_val <_s rs2_val, + RISCV_BGE => rs1_val >=_s rs2_val, + RISCV_BLTU => rs1_val <_u rs2_val, + RISCV_BGEU => rs1_val >=_u rs2_val + }; + let t : xlenbits = PC + sign_extend(imm); + if taken then { + /* Extensions get the first checks on the prospective target address. */ + match ext_control_check_pc(t) { + Ext_ControlAddr_Error(e) => { + ext_handle_control_check_error(e); + RETIRE_FAIL + }, + Ext_ControlAddr_OK(target) => { + if bit_to_bool(target[1]) & not(extension("C")) then { + handle_mem_exception(target, E_Fetch_Addr_Align()); + RETIRE_FAIL; + } else { + set_next_pc(target); + RETIRE_SUCCESS } } - } else RETIRE_SUCCESS - } - - + } + } else RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/bne.yaml b/arch/inst/I/bne.yaml index 579645344..099ba0db8 100644 --- a/arch/inst/I/bne.yaml +++ b/arch/inst/I/bne.yaml @@ -1,72 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -bne: - long_name: Branch if not equal - description: | - Branch to PC + imm if - the value in register rs1 is not equal to the value in register rs2. +$schema: "inst_schema.json#" +kind: instruction +name: bne +long_name: Branch if not equal +description: | + Branch to PC + imm if + the value in register rs1 is not equal to the value in register rs2. - Raise a `MisalignedAddress` exception if PC + imm is misaligned. - definedBy: I - assembly: xs1, xs2, imm - encoding: - match: -----------------001-----1100011 - variables: - - name: imm - location: 31|7|30-25|11-8 - left_shift: 1 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg lhs = X[rs1]; - XReg rhs = X[rs2]; + Raise a `MisalignedAddress` exception if PC + imm is misaligned. +definedBy: I +assembly: xs1, xs2, imm +encoding: + match: -----------------001-----1100011 + variables: + - name: imm + location: 31|7|30-25|11-8 + left_shift: 1 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg lhs = X[rs1]; + XReg rhs = X[rs2]; - if (lhs != rhs) { - jump_halfword($pc + imm); - } - + if (lhs != rhs) { + jump_halfword($pc + imm); + } + - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let taken : bool = match op { - RISCV_BEQ => rs1_val == rs2_val, - RISCV_BNE => rs1_val != rs2_val, - RISCV_BLT => rs1_val <_s rs2_val, - RISCV_BGE => rs1_val >=_s rs2_val, - RISCV_BLTU => rs1_val <_u rs2_val, - RISCV_BGEU => rs1_val >=_u rs2_val - }; - let t : xlenbits = PC + sign_extend(imm); - if taken then { - /* Extensions get the first checks on the prospective target address. */ - match ext_control_check_pc(t) { - Ext_ControlAddr_Error(e) => { - ext_handle_control_check_error(e); - RETIRE_FAIL - }, - Ext_ControlAddr_OK(target) => { - if bit_to_bool(target[1]) & not(extension("C")) then { - handle_mem_exception(target, E_Fetch_Addr_Align()); - RETIRE_FAIL; - } else { - set_next_pc(target); - RETIRE_SUCCESS - } +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let taken : bool = match op { + RISCV_BEQ => rs1_val == rs2_val, + RISCV_BNE => rs1_val != rs2_val, + RISCV_BLT => rs1_val <_s rs2_val, + RISCV_BGE => rs1_val >=_s rs2_val, + RISCV_BLTU => rs1_val <_u rs2_val, + RISCV_BGEU => rs1_val >=_u rs2_val + }; + let t : xlenbits = PC + sign_extend(imm); + if taken then { + /* Extensions get the first checks on the prospective target address. */ + match ext_control_check_pc(t) { + Ext_ControlAddr_Error(e) => { + ext_handle_control_check_error(e); + RETIRE_FAIL + }, + Ext_ControlAddr_OK(target) => { + if bit_to_bool(target[1]) & not(extension("C")) then { + handle_mem_exception(target, E_Fetch_Addr_Align()); + RETIRE_FAIL; + } else { + set_next_pc(target); + RETIRE_SUCCESS } } - } else RETIRE_SUCCESS - } - - + } + } else RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/ebreak.yaml b/arch/inst/I/ebreak.yaml index fe7ae0232..5b08b202d 100644 --- a/arch/inst/I/ebreak.yaml +++ b/arch/inst/I/ebreak.yaml @@ -1,44 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -ebreak: - long_name: Breakpoint exception - description: | - The EBREAK instruction is used by debuggers to cause control to be transferred back to - a debugging environment. Unless overridden by an external debug environment, - EBREAK raises a breakpoint exception and performs no other operation. - - [NOTE] - As described in the `C` Standard Extension for Compressed Instructions, the `c.ebreak` - instruction performs the same operation as the EBREAK instruction. - - EBREAK causes the receiving privilege mode's epc register to be set to the address of - the EBREAK instruction itself, not the address of the following instruction. - As EBREAK causes a synchronous exception, it is not considered to retire, - and should not increment the `minstret` CSR. - definedBy: I - assembly: '' - encoding: - match: '00000000000100000000000001110011' - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (TRAP_ON_EBREAK) { - raise_precise(ExceptionCode::Breakpoint, mode(), $pc); - } else { - eei_ebreak(); - } - - - - sail(): | - { - handle_mem_exception(PC, E_Breakpoint()); - RETIRE_FAIL - } - - +$schema: "inst_schema.json#" +kind: instruction +name: ebreak +long_name: Breakpoint exception +description: | + The EBREAK instruction is used by debuggers to cause control to be transferred back to + a debugging environment. Unless overridden by an external debug environment, + EBREAK raises a breakpoint exception and performs no other operation. + + [NOTE] + As described in the `C` Standard Extension for Compressed Instructions, the `c.ebreak` + instruction performs the same operation as the EBREAK instruction. + + EBREAK causes the receiving privilege mode's epc register to be set to the address of + the EBREAK instruction itself, not the address of the following instruction. + As EBREAK causes a synchronous exception, it is not considered to retire, + and should not increment the `minstret` CSR. +definedBy: I +assembly: '' +encoding: + match: '00000000000100000000000001110011' +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (TRAP_ON_EBREAK) { + raise_precise(ExceptionCode::Breakpoint, mode(), $pc); + } else { + eei_ebreak(); + } + + + +sail(): | + { + handle_mem_exception(PC, E_Breakpoint()); + RETIRE_FAIL + } + + diff --git a/arch/inst/I/ecall.yaml b/arch/inst/I/ecall.yaml index 93c4f1f14..2e6eb97d8 100644 --- a/arch/inst/I/ecall.yaml +++ b/arch/inst/I/ecall.yaml @@ -1,75 +1,77 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -ecall: - long_name: Environment call - description: | - The ECALL instruction is used to make a request to the supporting execution environment. - When executed in U-mode, S-mode, or M-mode, it generates an environment-call-from-U-mode - exception, environment-call-from-S-mode exception, or environment-call-from-M-mode - exception, respectively, and performs no other operation. +$schema: "inst_schema.json#" +kind: instruction +name: ecall +long_name: Environment call +description: | + The ECALL instruction is used to make a request to the supporting execution environment. + When executed in U-mode, S-mode, or M-mode, it generates an environment-call-from-U-mode + exception, environment-call-from-S-mode exception, or environment-call-from-M-mode + exception, respectively, and performs no other operation. - [NOTE] - ECALL generates a different exception for each originating privilege mode so that - environment call exceptions can be selectively delegated. - A typical use case for Unix-like operating systems is to delegate to S-mode - the environment-call-from-U-mode exception but not the others. + [NOTE] + ECALL generates a different exception for each originating privilege mode so that + environment call exceptions can be selectively delegated. + A typical use case for Unix-like operating systems is to delegate to S-mode + the environment-call-from-U-mode exception but not the others. - ECALL causes the receiving privilege mode's epc register to be set to the address of - the ECALL instruction itself, not the address of the following instruction. - As ECALL causes a synchronous exception, it is not considered to retire, - and should not increment the `minstret` CSR. - definedBy: I - assembly: '' - encoding: - match: '00000000000000000000000001110011' - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (mode() == PrivilegeMode::M) { - if (TRAP_ON_ECALL_FROM_M) { - raise_precise(ExceptionCode::Mcall, PrivilegeMode::M, 0); - } else { - eei_ecall_from_m(); - } - } else if (mode() == PrivilegeMode::S) { - if (TRAP_ON_ECALL_FROM_S) { - raise_precise(ExceptionCode::Scall, PrivilegeMode::S, 0); - } else { - eei_ecall_from_s(); - } - } else if (mode() == PrivilegeMode::U || mode() == PrivilegeMode::VU) { - if (TRAP_ON_ECALL_FROM_U) { - raise_precise(ExceptionCode::Ucall, mode(), 0); - } else { - eei_ecall_from_u(); - } - } else if (mode() == PrivilegeMode::VS) { - if (TRAP_ON_ECALL_FROM_VS) { - raise_precise(ExceptionCode::VScall, PrivilegeMode::VS, 0); - } else { - eei_ecall_from_vs(); - } + ECALL causes the receiving privilege mode's epc register to be set to the address of + the ECALL instruction itself, not the address of the following instruction. + As ECALL causes a synchronous exception, it is not considered to retire, + and should not increment the `minstret` CSR. +definedBy: I +assembly: '' +encoding: + match: '00000000000000000000000001110011' +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (mode() == PrivilegeMode::M) { + if (TRAP_ON_ECALL_FROM_M) { + raise_precise(ExceptionCode::Mcall, PrivilegeMode::M, 0); + } else { + eei_ecall_from_m(); } + } else if (mode() == PrivilegeMode::S) { + if (TRAP_ON_ECALL_FROM_S) { + raise_precise(ExceptionCode::Scall, PrivilegeMode::S, 0); + } else { + eei_ecall_from_s(); + } + } else if (mode() == PrivilegeMode::U || mode() == PrivilegeMode::VU) { + if (TRAP_ON_ECALL_FROM_U) { + raise_precise(ExceptionCode::Ucall, mode(), 0); + } else { + eei_ecall_from_u(); + } + } else if (mode() == PrivilegeMode::VS) { + if (TRAP_ON_ECALL_FROM_VS) { + raise_precise(ExceptionCode::VScall, PrivilegeMode::VS, 0); + } else { + eei_ecall_from_vs(); + } + } - sail(): | - { - let t : sync_exception = - struct { trap = match (cur_privilege) { - User => E_U_EnvCall(), - Supervisor => E_S_EnvCall(), - Machine => E_M_EnvCall() - }, - excinfo = (None() : option(xlenbits)), - ext = None() }; - set_next_pc(exception_handler(cur_privilege, CTL_TRAP(t), PC)); - RETIRE_FAIL - } - - +sail(): | + { + let t : sync_exception = + struct { trap = match (cur_privilege) { + User => E_U_EnvCall(), + Supervisor => E_S_EnvCall(), + Machine => E_M_EnvCall() + }, + excinfo = (None() : option(xlenbits)), + ext = None() }; + set_next_pc(exception_handler(cur_privilege, CTL_TRAP(t), PC)); + RETIRE_FAIL + } + + diff --git a/arch/inst/I/fence.yaml b/arch/inst/I/fence.yaml index db74a1e0e..8edbc5776 100644 --- a/arch/inst/I/fence.yaml +++ b/arch/inst/I/fence.yaml @@ -1,240 +1,242 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fence: - long_name: Memory ordering fence - description: | - Orders memory operations. - - The `fence` instruction is used to order device I/O and memory accesses as - viewed by other RISC-V harts and external devices or coprocessors. Any - combination of device input (I), device output (O), memory reads \(R), - and memory writes (W) may be ordered with respect to any combination of - the same. Informally, no other RISC-V hart or external device can - observe any operation in the _successor_ set following a `fence` before - any operation in the _predecessor_ set preceding the `fence`. - - The predecessor and successor fields have the same format to specify operation types: - - [%autowidth] - |=== - 4+| `pred` 4+| `succ` - - | 27 | 26 |25 | 24 | 23 | 22 | 21| 20 - | PI | PO |PR | PW | SI | SO |SR | SW - |=== - - [%autowidth,align="center",cols="^1,^1,<3",options="header"] - .Fence mode encoding - |=== - |_fm_ field |Mnemonic |Meaning - |0000 |_none_ |Normal Fence - |1000 |TSO |With `FENCE RW,RW`: exclude write-to-read ordering; otherwise: _Reserved for future use._ - 2+|_other_ |_Reserved for future use._ - |=== - - When the mode field _fm_ is `0001` and both the predecessor and successor sets are 'RW', - then the instruction acts as a special-case `fence.tso`. `fence.tso` orders all load operations - in its predecessor set before all memory operations in its successor set, and all store operations - in its predecessor set before all store operations in its successor set. This leaves non-AMO store - operations in the 'fence.tso's predecessor set unordered with non-AMO loads in its successor set. - - When mode field _fm_ is not `0001`, or when mode field _fm_ is `0001` but the _pred_ and - _succ_ fields are not both 'RW' (0x3), then the fence acts as a baseline fence (_e.g._, _fm_ is - effectively `0000`). This is unaffected by the FIOM bits, described below (implicit promotion does - not change how `fence.tso` is decoded). - - The `rs1` and `rd` fields are unused and ignored. - - In modes other than M-mode, `fence` is further affected by `menvcfg.FIOM`, - `senvcfg.FIOM`<% if ext?(:H) %>, and/or `henvcfg.FIOM`<% end %> - as follows: - - .Effective PR/PW/SR/SW in (H)S-mode - [%autowidth,cols=",,,",options="header",separator="!"] - !=== - ! [.rotate]#`menvcfg.FIOM`# ! `pred.PI` + - `pred.PO` + - `succ.SI` + - `succ.SO` - ! -> + - -> + - -> + - -> - ! effective `PR` + - effective `PW` + - effective `SR` + - effective `SW` - - ! 0 ! - ! ! from encoding - ! 1 ! 0 ! ! from encoding - ! 1 ! 1 ! ! 1 - !=== - - .Effective PR/PW/SR/SW in U-mode - [%autowidth,options="header",separator="!",cols=",,,,"] - !=== - ! [.rotate]#`menvcfg.FIOM`# ! [.rotate]#`senvcfg.FIOM`# ! `pred.PI` + - `pred.PO` + - `succ.SI` + - `succ.SO` - ! -> + - -> + - -> + - -> - ! effective `PR` + - effective `PW` + - effective `SR` + - effective `SW` - - ! 0 ! 0 ! - ! ! from encoding - ! 0 ! 1 ! 0 ! ! from encoding - ! 0 ! 1 ! 1 ! ! 1 - ! 1 ! - ! 0 ! ! from encoding - ! 1 ! - ! 1 ! ! 1 - !=== - - <%- if ext?(:H) -%> - .Effective PR/PW/SR/SW in VS-mode and VU-mode - [%autowidth,options="header",separator="!",cols=",,,,"] - !=== - ! [.rotate]#`menvcfg.FIOM`# ! [.rotate]#`henvcfg.FIOM`# ! `pred.PI` + - `pred.PO` + - `succ.SI` + - `succ.SO` - ! -> + - -> + - -> + - -> - ! effective `PR` + - effective `PW` + - effective `SR` + - effective `SW` - - ! 0 ! 0 ! - ! ! from encoding - ! 0 ! 1 ! 0 ! ! from encoding - ! 0 ! 1 ! 1 ! ! 1 - ! 1 ! - ! 0 ! ! from encoding - ! 1 ! - ! 1 ! ! 1 - !=== - <%- end -%> - - definedBy: I - assembly: "TODO" - encoding: - match: -----------------000-----0001111 - variables: - - name: fm - location: 31-28 - - name: pred - location: 27-24 - - name: succ - location: 23-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - Boolean is_fence_tso; - Boolean is_pause; - - if (fm == 1) { - if (pred == 0x3 && succ == 0x3) { - # this is a fence.tso instruction - is_fence_tso = true; - } +$schema: "inst_schema.json#" +kind: instruction +name: fence +long_name: Memory ordering fence +description: | + Orders memory operations. + + The `fence` instruction is used to order device I/O and memory accesses as + viewed by other RISC-V harts and external devices or coprocessors. Any + combination of device input (I), device output (O), memory reads \(R), + and memory writes (W) may be ordered with respect to any combination of + the same. Informally, no other RISC-V hart or external device can + observe any operation in the _successor_ set following a `fence` before + any operation in the _predecessor_ set preceding the `fence`. + + The predecessor and successor fields have the same format to specify operation types: + + [%autowidth] + |=== + 4+| `pred` 4+| `succ` + + | 27 | 26 |25 | 24 | 23 | 22 | 21| 20 + | PI | PO |PR | PW | SI | SO |SR | SW + |=== + + [%autowidth,align="center",cols="^1,^1,<3",options="header"] + .Fence mode encoding + |=== + |_fm_ field |Mnemonic |Meaning + |0000 |_none_ |Normal Fence + |1000 |TSO |With `FENCE RW,RW`: exclude write-to-read ordering; otherwise: _Reserved for future use._ + 2+|_other_ |_Reserved for future use._ + |=== + + When the mode field _fm_ is `0001` and both the predecessor and successor sets are 'RW', + then the instruction acts as a special-case `fence.tso`. `fence.tso` orders all load operations + in its predecessor set before all memory operations in its successor set, and all store operations + in its predecessor set before all store operations in its successor set. This leaves non-AMO store + operations in the 'fence.tso's predecessor set unordered with non-AMO loads in its successor set. + + When mode field _fm_ is not `0001`, or when mode field _fm_ is `0001` but the _pred_ and + _succ_ fields are not both 'RW' (0x3), then the fence acts as a baseline fence (_e.g._, _fm_ is + effectively `0000`). This is unaffected by the FIOM bits, described below (implicit promotion does + not change how `fence.tso` is decoded). + + The `rs1` and `rd` fields are unused and ignored. + + In modes other than M-mode, `fence` is further affected by `menvcfg.FIOM`, + `senvcfg.FIOM`<% if ext?(:H) %>, and/or `henvcfg.FIOM`<% end %> + as follows: + + .Effective PR/PW/SR/SW in (H)S-mode + [%autowidth,cols=",,,",options="header",separator="!"] + !=== + ! [.rotate]#`menvcfg.FIOM`# ! `pred.PI` + + `pred.PO` + + `succ.SI` + + `succ.SO` + ! -> + + -> + + -> + + -> + ! effective `PR` + + effective `PW` + + effective `SR` + + effective `SW` + + ! 0 ! - ! ! from encoding + ! 1 ! 0 ! ! from encoding + ! 1 ! 1 ! ! 1 + !=== + + .Effective PR/PW/SR/SW in U-mode + [%autowidth,options="header",separator="!",cols=",,,,"] + !=== + ! [.rotate]#`menvcfg.FIOM`# ! [.rotate]#`senvcfg.FIOM`# ! `pred.PI` + + `pred.PO` + + `succ.SI` + + `succ.SO` + ! -> + + -> + + -> + + -> + ! effective `PR` + + effective `PW` + + effective `SR` + + effective `SW` + + ! 0 ! 0 ! - ! ! from encoding + ! 0 ! 1 ! 0 ! ! from encoding + ! 0 ! 1 ! 1 ! ! 1 + ! 1 ! - ! 0 ! ! from encoding + ! 1 ! - ! 1 ! ! 1 + !=== + + <%- if ext?(:H) -%> + .Effective PR/PW/SR/SW in VS-mode and VU-mode + [%autowidth,options="header",separator="!",cols=",,,,"] + !=== + ! [.rotate]#`menvcfg.FIOM`# ! [.rotate]#`henvcfg.FIOM`# ! `pred.PI` + + `pred.PO` + + `succ.SI` + + `succ.SO` + ! -> + + -> + + -> + + -> + ! effective `PR` + + effective `PW` + + effective `SR` + + effective `SW` + + ! 0 ! 0 ! - ! ! from encoding + ! 0 ! 1 ! 0 ! ! from encoding + ! 0 ! 1 ! 1 ! ! 1 + ! 1 ! - ! 0 ! ! from encoding + ! 1 ! - ! 1 ! ! 1 + !=== + <%- end -%> + +definedBy: I +assembly: "TODO" +encoding: + match: -----------------000-----0001111 + variables: + - name: fm + location: 31-28 + - name: pred + location: 27-24 + - name: succ + location: 23-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + Boolean is_fence_tso; + Boolean is_pause; + + if (fm == 1) { + if (pred == 0x3 && succ == 0x3) { + # this is a fence.tso instruction + is_fence_tso = true; } - if (implemented?(ExtensionName::Zihintpause)) { - if ((pred == 1) && (succ == 0) && (fm == 0) && (rd == 0) && (rs1 == 0)) { - # this is a PAUSE instruction - is_pause = true; - } + } + if (implemented?(ExtensionName::Zihintpause)) { + if ((pred == 1) && (succ == 0) && (fm == 0) && (rd == 0) && (rs1 == 0)) { + # this is a PAUSE instruction + is_pause = true; } - - Boolean pred_i = pred[3] == 1; - Boolean pred_o = pred[2] == 1; - Boolean pred_r = pred[1] == 1; - Boolean pred_w = pred[0] == 1; - - Boolean succ_i = succ[3] == 1; - Boolean succ_o = succ[2] == 1; - Boolean succ_r = succ[1] == 1; - Boolean succ_w = succ[0] == 1; - - if (is_fence_tso) { - fence_tso(); - } else if (is_pause) { - pause(); - } else { - - # apply FIOM overrides - if (mode() == PrivilegeMode::S) { - if (CSR[menvcfg].FIOM == 1) { - if (pred_i) { pred_r = true; } - if (pred_o) { pred_w = true; } - if (succ_i) { succ_r = true; } - if (succ_o) { succ_w = true; } - } - } else if (mode() == PrivilegeMode::U) { - if ((CSR[menvcfg].FIOM | CSR[senvcfg].FIOM) == 1) { - if (pred_i) { pred_r = true; } - if (pred_o) { pred_w = true; } - if (succ_i) { succ_r = true; } - if (succ_o) { succ_w = true; } - } - } else if (mode() == PrivilegeMode::VS || mode() == PrivilegeMode::VU) { - if ((CSR[menvcfg].FIOM | CSR[henvcfg].FIOM) == 1) { - if (pred_i) { pred_r = true; } - if (pred_o) { pred_w = true; } - if (succ_i) { succ_r = true; } - if (succ_o) { succ_w = true; } - } + } + + Boolean pred_i = pred[3] == 1; + Boolean pred_o = pred[2] == 1; + Boolean pred_r = pred[1] == 1; + Boolean pred_w = pred[0] == 1; + + Boolean succ_i = succ[3] == 1; + Boolean succ_o = succ[2] == 1; + Boolean succ_r = succ[1] == 1; + Boolean succ_w = succ[0] == 1; + + if (is_fence_tso) { + fence_tso(); + } else if (is_pause) { + pause(); + } else { + + # apply FIOM overrides + if (mode() == PrivilegeMode::S) { + if (CSR[menvcfg].FIOM == 1) { + if (pred_i) { pred_r = true; } + if (pred_o) { pred_w = true; } + if (succ_i) { succ_r = true; } + if (succ_o) { succ_w = true; } } - - fence( - pred_i, pred_o, pred_r, pred_w, - succ_i, succ_o, succ_r, succ_w - ); - } - pseudoinstructions: - - when: (pred == 0x3) && (succ == 0x3) && (fm == 1) - to: fence.tso - - when: (pred == 1) && (succ == 0) && (fm == 0) && (rd == 0) && (rs1 == 0) - to: pause - - - - sail(): | - { - // If the FIOM bit in menvcfg/senvcfg is set then the I/O bits can imply R/W. - let fiom = is_fiom_active(); - let pred = effective_fence_set(pred, fiom); - let succ = effective_fence_set(succ, fiom); - - match (pred, succ) { - (_ : bits(2) @ 0b11, _ : bits(2) @ 0b11) => __barrier(Barrier_RISCV_rw_rw()), - (_ : bits(2) @ 0b10, _ : bits(2) @ 0b11) => __barrier(Barrier_RISCV_r_rw()), - (_ : bits(2) @ 0b10, _ : bits(2) @ 0b10) => __barrier(Barrier_RISCV_r_r()), - (_ : bits(2) @ 0b11, _ : bits(2) @ 0b01) => __barrier(Barrier_RISCV_rw_w()), - (_ : bits(2) @ 0b01, _ : bits(2) @ 0b01) => __barrier(Barrier_RISCV_w_w()), - (_ : bits(2) @ 0b01, _ : bits(2) @ 0b11) => __barrier(Barrier_RISCV_w_rw()), - (_ : bits(2) @ 0b11, _ : bits(2) @ 0b10) => __barrier(Barrier_RISCV_rw_r()), - (_ : bits(2) @ 0b10, _ : bits(2) @ 0b01) => __barrier(Barrier_RISCV_r_w()), - (_ : bits(2) @ 0b01, _ : bits(2) @ 0b10) => __barrier(Barrier_RISCV_w_r()), - - (_ : bits(4) , _ : bits(2) @ 0b00) => (), - (_ : bits(2) @ 0b00, _ : bits(4) ) => (), - - _ => { print("FIXME: unsupported fence"); - () } - }; - RETIRE_SUCCESS + } else if (mode() == PrivilegeMode::U) { + if ((CSR[menvcfg].FIOM | CSR[senvcfg].FIOM) == 1) { + if (pred_i) { pred_r = true; } + if (pred_o) { pred_w = true; } + if (succ_i) { succ_r = true; } + if (succ_o) { succ_w = true; } + } + } else if (mode() == PrivilegeMode::VS || mode() == PrivilegeMode::VU) { + if ((CSR[menvcfg].FIOM | CSR[henvcfg].FIOM) == 1) { + if (pred_i) { pred_r = true; } + if (pred_o) { pred_w = true; } + if (succ_i) { succ_r = true; } + if (succ_o) { succ_w = true; } + } } + + fence( + pred_i, pred_o, pred_r, pred_w, + succ_i, succ_o, succ_r, succ_w + ); + } +pseudoinstructions: +- when: (pred == 0x3) && (succ == 0x3) && (fm == 1) + to: fence.tso +- when: (pred == 1) && (succ == 0) && (fm == 0) && (rd == 0) && (rs1 == 0) + to: pause + + + +sail(): | + { + // If the FIOM bit in menvcfg/senvcfg is set then the I/O bits can imply R/W. + let fiom = is_fiom_active(); + let pred = effective_fence_set(pred, fiom); + let succ = effective_fence_set(succ, fiom); + + match (pred, succ) { + (_ : bits(2) @ 0b11, _ : bits(2) @ 0b11) => __barrier(Barrier_RISCV_rw_rw()), + (_ : bits(2) @ 0b10, _ : bits(2) @ 0b11) => __barrier(Barrier_RISCV_r_rw()), + (_ : bits(2) @ 0b10, _ : bits(2) @ 0b10) => __barrier(Barrier_RISCV_r_r()), + (_ : bits(2) @ 0b11, _ : bits(2) @ 0b01) => __barrier(Barrier_RISCV_rw_w()), + (_ : bits(2) @ 0b01, _ : bits(2) @ 0b01) => __barrier(Barrier_RISCV_w_w()), + (_ : bits(2) @ 0b01, _ : bits(2) @ 0b11) => __barrier(Barrier_RISCV_w_rw()), + (_ : bits(2) @ 0b11, _ : bits(2) @ 0b10) => __barrier(Barrier_RISCV_rw_r()), + (_ : bits(2) @ 0b10, _ : bits(2) @ 0b01) => __barrier(Barrier_RISCV_r_w()), + (_ : bits(2) @ 0b01, _ : bits(2) @ 0b10) => __barrier(Barrier_RISCV_w_r()), + (_ : bits(4) , _ : bits(2) @ 0b00) => (), + (_ : bits(2) @ 0b00, _ : bits(4) ) => (), + _ => { print("FIXME: unsupported fence"); + () } + }; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/jal.yaml b/arch/inst/I/jal.yaml index 19a28905c..fdd537478 100644 --- a/arch/inst/I/jal.yaml +++ b/arch/inst/I/jal.yaml @@ -1,58 +1,60 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -jal: - long_name: Jump and link - description: | - Jump to a PC-relative offset and store the return - address in rd. - definedBy: I - assembly: xd, imm - encoding: - match: -------------------------1101111 - variables: - - name: imm - location: 31|19-12|20|30-21 - left_shift: 1 - sign_extend: true - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg retrun_addr = $pc + 4; - - jump_halfword($pc + imm); - X[rd] = retrun_addr; - - - - sail(): | - { - let t : xlenbits = PC + sign_extend(imm); - /* Extensions get the first checks on the prospective target address. */ - match ext_control_check_pc(t) { - Ext_ControlAddr_Error(e) => { - ext_handle_control_check_error(e); +$schema: "inst_schema.json#" +kind: instruction +name: jal +long_name: Jump and link +description: | + Jump to a PC-relative offset and store the return + address in rd. +definedBy: I +assembly: xd, imm +encoding: + match: -------------------------1101111 + variables: + - name: imm + location: 31|19-12|20|30-21 + left_shift: 1 + sign_extend: true + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg retrun_addr = $pc + 4; + + jump_halfword($pc + imm); + X[rd] = retrun_addr; + + + +sail(): | + { + let t : xlenbits = PC + sign_extend(imm); + /* Extensions get the first checks on the prospective target address. */ + match ext_control_check_pc(t) { + Ext_ControlAddr_Error(e) => { + ext_handle_control_check_error(e); + RETIRE_FAIL + }, + Ext_ControlAddr_OK(target) => { + /* Perform standard alignment check */ + if bit_to_bool(target[1]) & not(extension("C")) + then { + handle_mem_exception(target, E_Fetch_Addr_Align()); RETIRE_FAIL - }, - Ext_ControlAddr_OK(target) => { - /* Perform standard alignment check */ - if bit_to_bool(target[1]) & not(extension("C")) - then { - handle_mem_exception(target, E_Fetch_Addr_Align()); - RETIRE_FAIL - } else { - X(rd) = get_next_pc(); - set_next_pc(target); - RETIRE_SUCCESS - } + } else { + X(rd) = get_next_pc(); + set_next_pc(target); + RETIRE_SUCCESS } } } - - + } + + diff --git a/arch/inst/I/jalr.yaml b/arch/inst/I/jalr.yaml index 786e3bd2f..d3aebbf17 100644 --- a/arch/inst/I/jalr.yaml +++ b/arch/inst/I/jalr.yaml @@ -1,64 +1,66 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -jalr: - long_name: Jump and link register - description: | - Jump to an address formed by adding rs1 - to a signed offset, and store the return address in rd. - definedBy: I - assembly: xd, imm(rs1) - encoding: - match: -----------------000-----1100111 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg returnaddr; - returnaddr = $pc + 4; +$schema: "inst_schema.json#" +kind: instruction +name: jalr +long_name: Jump and link register +description: | + Jump to an address formed by adding rs1 + to a signed offset, and store the return address in rd. +definedBy: I +assembly: xd, imm(rs1) +encoding: + match: -----------------000-----1100111 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg returnaddr; + returnaddr = $pc + 4; - jump(X[rs1] + imm); - X[rd] = returnaddr; + jump(X[rs1] + imm); + X[rd] = returnaddr; - sail(): | - { - /* For the sequential model, the memory-model definition doesn't work directly - * if rs1 = rd. We would effectively have to keep a regfile for reads and another for - * writes, and swap on instruction completion. This could perhaps be optimized in - * some manner, but for now, we just keep a reordered definition to improve simulator - * performance. - */ - let t : xlenbits = X(rs1) + sign_extend(imm); - /* Extensions get the first checks on the prospective target address. */ - match ext_control_check_addr(t) { - Ext_ControlAddr_Error(e) => { - ext_handle_control_check_error(e); +sail(): | + { + /* For the sequential model, the memory-model definition doesn't work directly + * if rs1 = rd. We would effectively have to keep a regfile for reads and another for + * writes, and swap on instruction completion. This could perhaps be optimized in + * some manner, but for now, we just keep a reordered definition to improve simulator + * performance. + */ + let t : xlenbits = X(rs1) + sign_extend(imm); + /* Extensions get the first checks on the prospective target address. */ + match ext_control_check_addr(t) { + Ext_ControlAddr_Error(e) => { + ext_handle_control_check_error(e); + RETIRE_FAIL + }, + Ext_ControlAddr_OK(addr) => { + let target = [addr with 0 = bitzero]; /* clear addr[0] */ + if bit_to_bool(target[1]) & not(extension("C")) then { + handle_mem_exception(target, E_Fetch_Addr_Align()); RETIRE_FAIL - }, - Ext_ControlAddr_OK(addr) => { - let target = [addr with 0 = bitzero]; /* clear addr[0] */ - if bit_to_bool(target[1]) & not(extension("C")) then { - handle_mem_exception(target, E_Fetch_Addr_Align()); - RETIRE_FAIL - } else { - X(rd) = get_next_pc(); - set_next_pc(target); - RETIRE_SUCCESS - } + } else { + X(rd) = get_next_pc(); + set_next_pc(target); + RETIRE_SUCCESS } } } - - + } + + diff --git a/arch/inst/I/lb.yaml b/arch/inst/I/lb.yaml index a4306bf66..5c3f1edf9 100644 --- a/arch/inst/I/lb.yaml +++ b/arch/inst/I/lb.yaml @@ -1,62 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -lb: - long_name: Load byte - description: | - Load 8 bits of data into register `rd` from an - address formed by adding `rs1` to a signed offset. - Sign extend the result. - definedBy: I - assembly: xd, imm(rs1) - encoding: - match: -----------------000-----0000011 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg virtual_address = X[rs1] + imm; - - X[rd] = sext(read_memory<8>(virtual_address, $encoding), 8); - - - - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => - match (width) { - BYTE => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), - HALF => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), - WORD => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), - DOUBLE if sizeof(xlen) >= 64 => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), - _ => report_invalid_width(__FILE__, __LINE__, width, "load") - } - } - } +$schema: "inst_schema.json#" +kind: instruction +name: lb +long_name: Load byte +description: | + Load 8 bits of data into register `rd` from an + address formed by adding `rs1` to a signed offset. + Sign extend the result. +definedBy: I +assembly: xd, imm(rs1) +encoding: + match: -----------------000-----0000011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg virtual_address = X[rs1] + imm; + + X[rd] = sext(read_memory<8>(virtual_address, $encoding), 8); + + + +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } } - - + } + + diff --git a/arch/inst/I/lbu.yaml b/arch/inst/I/lbu.yaml index 9b9c08bea..ac4cd38a4 100644 --- a/arch/inst/I/lbu.yaml +++ b/arch/inst/I/lbu.yaml @@ -1,62 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -lbu: - long_name: Load byte unsigned - description: | - Load 8 bits of data into register `rd` from an - address formed by adding `rs1` to a signed offset. - Zero extend the result. - definedBy: I - assembly: xd, imm(rs1) - encoding: - match: -----------------100-----0000011 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg virtual_address = X[rs1] + imm; - - X[rd] = read_memory<8>(virtual_address, $encoding); - - - - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => - match (width) { - BYTE => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), - HALF => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), - WORD => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), - DOUBLE if sizeof(xlen) >= 64 => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), - _ => report_invalid_width(__FILE__, __LINE__, width, "load") - } - } - } +$schema: "inst_schema.json#" +kind: instruction +name: lbu +long_name: Load byte unsigned +description: | + Load 8 bits of data into register `rd` from an + address formed by adding `rs1` to a signed offset. + Zero extend the result. +definedBy: I +assembly: xd, imm(rs1) +encoding: + match: -----------------100-----0000011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg virtual_address = X[rs1] + imm; + + X[rd] = read_memory<8>(virtual_address, $encoding); + + + +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } } - - + } + + diff --git a/arch/inst/I/ld.yaml b/arch/inst/I/ld.yaml index 1398190fe..c4c23b40b 100644 --- a/arch/inst/I/ld.yaml +++ b/arch/inst/I/ld.yaml @@ -1,62 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -ld: - long_name: Load doubleword - description: | - Load 64 bits of data into register `rd` from an - address formed by adding `rs1` to a signed offset. - definedBy: I - base: 64 - assembly: xd, imm(rs1) - encoding: - match: -----------------011-----0000011 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg virtual_address = X[rs1] + imm; - - X[rd] = read_memory<64>(virtual_address, $encoding); - - - - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => - match (width) { - BYTE => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), - HALF => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), - WORD => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), - DOUBLE if sizeof(xlen) >= 64 => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), - _ => report_invalid_width(__FILE__, __LINE__, width, "load") - } - } - } +$schema: "inst_schema.json#" +kind: instruction +name: ld +long_name: Load doubleword +description: | + Load 64 bits of data into register `rd` from an + address formed by adding `rs1` to a signed offset. +definedBy: I +base: 64 +assembly: xd, imm(rs1) +encoding: + match: -----------------011-----0000011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg virtual_address = X[rs1] + imm; + + X[rd] = read_memory<64>(virtual_address, $encoding); + + + +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } } - - + } + + diff --git a/arch/inst/I/lh.yaml b/arch/inst/I/lh.yaml index 60af91bf0..d316e61b8 100644 --- a/arch/inst/I/lh.yaml +++ b/arch/inst/I/lh.yaml @@ -1,62 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -lh: - long_name: Load halfword - description: | - Load 16 bits of data into register `rd` from an - address formed by adding `rs1` to a signed offset. - Sign extend the result. - definedBy: I - assembly: xd, imm(rs1) - encoding: - match: -----------------001-----0000011 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg virtual_address = X[rs1] + imm; - - X[rd] = sext(read_memory<16>(virtual_address, $encoding), 16); - - - - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => - match (width) { - BYTE => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), - HALF => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), - WORD => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), - DOUBLE if sizeof(xlen) >= 64 => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), - _ => report_invalid_width(__FILE__, __LINE__, width, "load") - } - } - } +$schema: "inst_schema.json#" +kind: instruction +name: lh +long_name: Load halfword +description: | + Load 16 bits of data into register `rd` from an + address formed by adding `rs1` to a signed offset. + Sign extend the result. +definedBy: I +assembly: xd, imm(rs1) +encoding: + match: -----------------001-----0000011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg virtual_address = X[rs1] + imm; + + X[rd] = sext(read_memory<16>(virtual_address, $encoding), 16); + + + +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } } - - + } + + diff --git a/arch/inst/I/lhu.yaml b/arch/inst/I/lhu.yaml index d068cfdb2..bea81ff05 100644 --- a/arch/inst/I/lhu.yaml +++ b/arch/inst/I/lhu.yaml @@ -1,62 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -lhu: - long_name: Load halfword unsigned - description: | - Load 16 bits of data into register `rd` from an - address formed by adding `rs1` to a signed offset. - Zero extend the result. - definedBy: I - assembly: xd, imm(rs1) - encoding: - match: -----------------101-----0000011 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg virtual_address = X[rs1] + imm; - - X[rd] = read_memory<16>(virtual_address, $encoding); - - - - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => - match (width) { - BYTE => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), - HALF => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), - WORD => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), - DOUBLE if sizeof(xlen) >= 64 => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), - _ => report_invalid_width(__FILE__, __LINE__, width, "load") - } - } - } +$schema: "inst_schema.json#" +kind: instruction +name: lhu +long_name: Load halfword unsigned +description: | + Load 16 bits of data into register `rd` from an + address formed by adding `rs1` to a signed offset. + Zero extend the result. +definedBy: I +assembly: xd, imm(rs1) +encoding: + match: -----------------101-----0000011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg virtual_address = X[rs1] + imm; + + X[rd] = read_memory<16>(virtual_address, $encoding); + + + +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } } - - + } + + diff --git a/arch/inst/I/lui.yaml b/arch/inst/I/lui.yaml index 1dc0f8499..4253ddb06 100644 --- a/arch/inst/I/lui.yaml +++ b/arch/inst/I/lui.yaml @@ -1,39 +1,41 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -lui: - long_name: Load upper immediate - description: Load the zero-extended imm into rd. - definedBy: I - assembly: xd, imm - encoding: - match: -------------------------0110111 - variables: - - name: imm - location: 31-12 - left_shift: 12 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): X[rd] = imm; - - - - sail(): | - { - let off : xlenbits = sign_extend(imm @ 0x000); - let ret : xlenbits = match op { - RISCV_LUI => off, - RISCV_AUIPC => get_arch_pc() + off - }; - X(rd) = ret; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: lui +long_name: Load upper immediate +description: Load the zero-extended imm into rd. +definedBy: I +assembly: xd, imm +encoding: + match: -------------------------0110111 + variables: + - name: imm + location: 31-12 + left_shift: 12 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): X[rd] = imm; + + + +sail(): | + { + let off : xlenbits = sign_extend(imm @ 0x000); + let ret : xlenbits = match op { + RISCV_LUI => off, + RISCV_AUIPC => get_arch_pc() + off + }; + X(rd) = ret; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/lw.yaml b/arch/inst/I/lw.yaml index 47cb0a0d5..99b721a42 100644 --- a/arch/inst/I/lw.yaml +++ b/arch/inst/I/lw.yaml @@ -1,62 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -lw: - long_name: Load word - description: | - Load 32 bits of data into register `rd` from an - address formed by adding `rs1` to a signed offset. - Sign extend the result. - definedBy: I - assembly: xd, imm(rs1) - encoding: - match: -----------------010-----0000011 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg virtual_address = X[rs1] + imm; - - X[rd] = read_memory<32>(virtual_address, $encoding); - - - - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => - match (width) { - BYTE => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), - HALF => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), - WORD => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), - DOUBLE if sizeof(xlen) >= 64 => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), - _ => report_invalid_width(__FILE__, __LINE__, width, "load") - } - } - } +$schema: "inst_schema.json#" +kind: instruction +name: lw +long_name: Load word +description: | + Load 32 bits of data into register `rd` from an + address formed by adding `rs1` to a signed offset. + Sign extend the result. +definedBy: I +assembly: xd, imm(rs1) +encoding: + match: -----------------010-----0000011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg virtual_address = X[rs1] + imm; + + X[rd] = read_memory<32>(virtual_address, $encoding); + + + +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } } - - + } + + diff --git a/arch/inst/I/lwu.yaml b/arch/inst/I/lwu.yaml index fa8818329..c33be3984 100644 --- a/arch/inst/I/lwu.yaml +++ b/arch/inst/I/lwu.yaml @@ -1,63 +1,65 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -lwu: - long_name: Load word unsigned - description: | - Load 64 bits of data into register `rd` from an - address formed by adding `rs1` to a signed offset. - Zero extend the result. - definedBy: I - base: 64 - assembly: xd, imm(rs1) - encoding: - match: -----------------110-----0000011 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg virtual_address = X[rs1] + imm; - - X[rd] = read_memory<32>(virtual_address, $encoding); - - - - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => - match (width) { - BYTE => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), - HALF => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), - WORD => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), - DOUBLE if sizeof(xlen) >= 64 => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), - _ => report_invalid_width(__FILE__, __LINE__, width, "load") - } - } - } +$schema: "inst_schema.json#" +kind: instruction +name: lwu +long_name: Load word unsigned +description: | + Load 64 bits of data into register `rd` from an + address formed by adding `rs1` to a signed offset. + Zero extend the result. +definedBy: I +base: 64 +assembly: xd, imm(rs1) +encoding: + match: -----------------110-----0000011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg virtual_address = X[rs1] + imm; + + X[rd] = read_memory<32>(virtual_address, $encoding); + + + +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } } - - + } + + diff --git a/arch/inst/I/mret.yaml b/arch/inst/I/mret.yaml index a463001a5..356654adc 100644 --- a/arch/inst/I/mret.yaml +++ b/arch/inst/I/mret.yaml @@ -1,46 +1,48 @@ -mret: - long_name: Machine Exception Return - description: | - Returns from an exception in M-mode. - assembly: "" - definedBy: Sm - access: - s: never - u: never - vs: never - vu: never - encoding: - match: '00110000001000000000000001110011' - operation(): | - if (implemented?(ExtensionName::S) && CSR[mstatus].MPP != 2'b11) { - CSR[mstatus].MPRV = 0; - } - CSR[mstatus].MIE = CSR[mstatus].MPIE; - CSR[mstatus].MPIE = 1; - if (CSR[mstatus].MPP == 2'b00) { - set_mode(PrivilegeMode::U); - } else if (CSR[mstatus].MPP == 2'b01) { - set_mode(PrivilegeMode::S); - } else if (CSR[mstatus].MPP == 2'b11) { - set_mode(PrivilegeMode::M); - } - CSR[mstatus].MPP = implemented?(ExtensionName::U) ? 2'b00 : 2'b11; - $pc = $bits(CSR[mepc]); +$schema: "inst_schema.json#" +kind: instruction +name: mret +long_name: Machine Exception Return +description: | + Returns from an exception in M-mode. +assembly: "" +definedBy: Sm +access: + s: never + u: never + vs: never + vu: never +encoding: + match: '00110000001000000000000001110011' +operation(): | + if (implemented?(ExtensionName::S) && CSR[mstatus].MPP != 2'b11) { + CSR[mstatus].MPRV = 0; + } + CSR[mstatus].MIE = CSR[mstatus].MPIE; + CSR[mstatus].MPIE = 1; + if (CSR[mstatus].MPP == 2'b00) { + set_mode(PrivilegeMode::U); + } else if (CSR[mstatus].MPP == 2'b01) { + set_mode(PrivilegeMode::S); + } else if (CSR[mstatus].MPP == 2'b11) { + set_mode(PrivilegeMode::M); + } + CSR[mstatus].MPP = implemented?(ExtensionName::U) ? 2'b00 : 2'b11; + $pc = $bits(CSR[mepc]); - sail(): | - { - if cur_privilege != Machine - then { handle_illegal(); RETIRE_FAIL } - else if not(ext_check_xret_priv (Machine)) - then { ext_fail_xret_priv(); RETIRE_FAIL } - else { - set_next_pc(exception_handler(cur_privilege, CTL_MRET(), PC)); - RETIRE_SUCCESS - } +sail(): | + { + if cur_privilege != Machine + then { handle_illegal(); RETIRE_FAIL } + else if not(ext_check_xret_priv (Machine)) + then { ext_fail_xret_priv(); RETIRE_FAIL } + else { + set_next_pc(exception_handler(cur_privilege, CTL_MRET(), PC)); + RETIRE_SUCCESS } - - + } + + diff --git a/arch/inst/I/or.yaml b/arch/inst/I/or.yaml index 7bdabd251..43cb35a28 100644 --- a/arch/inst/I/or.yaml +++ b/arch/inst/I/or.yaml @@ -1,55 +1,57 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -or: - long_name: Or - description: Or rs1 with rs2, and store the result in rd - definedBy: I - assembly: xd, xs1, xs2 - encoding: - match: 0000000----------110-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): X[rd] = X[rs1] | X[rs2]; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: or +long_name: Or +description: Or rs1 with rs2, and store the result in rd +definedBy: I +assembly: xd, xs1, xs2 +encoding: + match: 0000000----------110-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): X[rd] = X[rs1] | X[rs2]; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/ori.yaml b/arch/inst/I/ori.yaml index caaa99ef4..fe8a2fa0b 100644 --- a/arch/inst/I/ori.yaml +++ b/arch/inst/I/ori.yaml @@ -1,70 +1,72 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -ori: - long_name: Or immediate - description: Or an immediate to the value in rs1, and store the result in rd - definedBy: I - assembly: xd, xs1, imm - encoding: - match: -----------------110-----0010011 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::Zicbop)) { - if (rd == 0) { - if (imm[4:0] == 0) { - # prefetch.i instruction - Bits<12> offset = {imm[11:5], rd}; - prefetch_instruction(offset); - } else if (imm[4:0] == 1) { - # prefetch.r instruction - Bits<12> offset = {imm[11:5], rd}; - prefetch_read(offset); - } else if (imm[4:0] == 3) { - # prefetch.r instruction - Bits<12> offset = {imm[11:5], rd}; - prefetch_write(offset); - } +$schema: "inst_schema.json#" +kind: instruction +name: ori +long_name: Or immediate +description: Or an immediate to the value in rs1, and store the result in rd +definedBy: I +assembly: xd, xs1, imm +encoding: + match: -----------------110-----0010011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::Zicbop)) { + if (rd == 0) { + if (imm[4:0] == 0) { + # prefetch.i instruction + Bits<12> offset = {imm[11:5], rd}; + prefetch_instruction(offset); + } else if (imm[4:0] == 1) { + # prefetch.r instruction + Bits<12> offset = {imm[11:5], rd}; + prefetch_read(offset); + } else if (imm[4:0] == 3) { + # prefetch.r instruction + Bits<12> offset = {imm[11:5], rd}; + prefetch_write(offset); } } - X[rd] = X[rs1] | imm; - pseudoinstructions: - - when: (rd == 0) && (imm[4:0] == 0) - to: prefetch.i offset - - when: (rd == 0) && (imm[4:0] == 1) - to: prefetch.r offset - - when: (rd == 0) && (imm[4:0] == 3) - to: prefetch.w offset + } + X[rd] = X[rs1] | imm; +pseudoinstructions: + - when: (rd == 0) && (imm[4:0] == 0) + to: prefetch.i offset + - when: (rd == 0) && (imm[4:0] == 1) + to: prefetch.r offset + - when: (rd == 0) && (imm[4:0] == 3) + to: prefetch.w offset - sail(): | - { - let rs1_val = X(rs1); - let immext : xlenbits = sign_extend(imm); - let result : xlenbits = match op { - RISCV_ADDI => rs1_val + immext, - RISCV_SLTI => zero_extend(bool_to_bits(rs1_val <_s immext)), - RISCV_SLTIU => zero_extend(bool_to_bits(rs1_val <_u immext)), - RISCV_ANDI => rs1_val & immext, - RISCV_ORI => rs1_val | immext, - RISCV_XORI => rs1_val ^ immext - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +sail(): | + { + let rs1_val = X(rs1); + let immext : xlenbits = sign_extend(imm); + let result : xlenbits = match op { + RISCV_ADDI => rs1_val + immext, + RISCV_SLTI => zero_extend(bool_to_bits(rs1_val <_s immext)), + RISCV_SLTIU => zero_extend(bool_to_bits(rs1_val <_u immext)), + RISCV_ANDI => rs1_val & immext, + RISCV_ORI => rs1_val | immext, + RISCV_XORI => rs1_val ^ immext + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/sb.yaml b/arch/inst/I/sb.yaml index 96f135c98..06054e650 100644 --- a/arch/inst/I/sb.yaml +++ b/arch/inst/I/sb.yaml @@ -1,76 +1,78 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sb: - long_name: Store byte - description: | - Store 8 bits of data from register `rs2` to an - address formed by adding `rs1` to a signed offset. - definedBy: I - assembly: xs2, imm(xs1) - encoding: - match: -----------------000-----0100011 - variables: - - name: imm - location: 31-25|11-7 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg virtual_address = X[rs1] + imm; +$schema: "inst_schema.json#" +kind: instruction +name: sb +long_name: Store byte +description: | + Store 8 bits of data from register `rs2` to an + address formed by adding `rs1` to a signed offset. +definedBy: I +assembly: xs2, imm(xs1) +encoding: + match: -----------------000-----0100011 + variables: + - name: imm + location: 31-25|11-7 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg virtual_address = X[rs1] + imm; - write_memory<8>(virtual_address, X[rs2][7:0], $encoding); + write_memory<8>(virtual_address, X[rs2][7:0], $encoding); - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Write(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Write(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => { - let eares : MemoryOpResult(unit) = match width { - BYTE => mem_write_ea(paddr, 1, aq, rl, false), - HALF => mem_write_ea(paddr, 2, aq, rl, false), - WORD => mem_write_ea(paddr, 4, aq, rl, false), - DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let rs2_val = X(rs2); - let res : MemoryOpResult(bool) = match (width) { - BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), - HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), - WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), - DOUBLE if sizeof(xlen) >= 64 - => mem_write_value(paddr, 8, rs2_val, aq, rl, false), - _ => report_invalid_width(__FILE__, __LINE__, width, "store"), - }; - match (res) { - MemValue(true) => RETIRE_SUCCESS, - MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Write(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Write(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => { + let eares : MemoryOpResult(unit) = match width { + BYTE => mem_write_ea(paddr, 1, aq, rl, false), + HALF => mem_write_ea(paddr, 2, aq, rl, false), + WORD => mem_write_ea(paddr, 4, aq, rl, false), + DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let rs2_val = X(rs2); + let res : MemoryOpResult(bool) = match (width) { + BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), + HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), + WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), + DOUBLE if sizeof(xlen) >= 64 + => mem_write_value(paddr, 8, rs2_val, aq, rl, false), + _ => report_invalid_width(__FILE__, __LINE__, width, "store"), + }; + match (res) { + MemValue(true) => RETIRE_SUCCESS, + MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } } - } + } } - - + } + + diff --git a/arch/inst/I/sd.yaml b/arch/inst/I/sd.yaml index a1416d8e3..62feb0693 100644 --- a/arch/inst/I/sd.yaml +++ b/arch/inst/I/sd.yaml @@ -1,78 +1,80 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sd: - long_name: Store doubleword - description: | - Store 64 bits of data from register `rs2` to an - address formed by adding `rs1` to a signed offset. - definedBy: I - base: 64 - assembly: xs2, imm(xs1) - encoding: - match: -----------------011-----0100011 - variables: - - name: imm - location: 31-25|11-7 - sign_extend: true - - name: rs1 - location: 19-15 - - name: rs2 - location: 24-20 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg virtual_address = X[rs1] + imm; +$schema: "inst_schema.json#" +kind: instruction +name: sd +long_name: Store doubleword +description: | + Store 64 bits of data from register `rs2` to an + address formed by adding `rs1` to a signed offset. +definedBy: I +base: 64 +assembly: xs2, imm(xs1) +encoding: + match: -----------------011-----0100011 + variables: + - name: imm + location: 31-25|11-7 + sign_extend: true + - name: rs1 + location: 19-15 + - name: rs2 + location: 24-20 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg virtual_address = X[rs1] + imm; - write_memory<64>(virtual_address, X[rs2], $encoding); + write_memory<64>(virtual_address, X[rs2], $encoding); - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Write(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Write(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => { - let eares : MemoryOpResult(unit) = match width { - BYTE => mem_write_ea(paddr, 1, aq, rl, false), - HALF => mem_write_ea(paddr, 2, aq, rl, false), - WORD => mem_write_ea(paddr, 4, aq, rl, false), - DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let rs2_val = X(rs2); - let res : MemoryOpResult(bool) = match (width) { - BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), - HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), - WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), - DOUBLE if sizeof(xlen) >= 64 - => mem_write_value(paddr, 8, rs2_val, aq, rl, false), - _ => report_invalid_width(__FILE__, __LINE__, width, "store"), - }; - match (res) { - MemValue(true) => RETIRE_SUCCESS, - MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Write(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Write(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => { + let eares : MemoryOpResult(unit) = match width { + BYTE => mem_write_ea(paddr, 1, aq, rl, false), + HALF => mem_write_ea(paddr, 2, aq, rl, false), + WORD => mem_write_ea(paddr, 4, aq, rl, false), + DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let rs2_val = X(rs2); + let res : MemoryOpResult(bool) = match (width) { + BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), + HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), + WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), + DOUBLE if sizeof(xlen) >= 64 + => mem_write_value(paddr, 8, rs2_val, aq, rl, false), + _ => report_invalid_width(__FILE__, __LINE__, width, "store"), + }; + match (res) { + MemValue(true) => RETIRE_SUCCESS, + MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } } - } + } } - - + } + + diff --git a/arch/inst/I/sh.yaml b/arch/inst/I/sh.yaml index ede6bac64..5331d4839 100644 --- a/arch/inst/I/sh.yaml +++ b/arch/inst/I/sh.yaml @@ -1,76 +1,78 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sh: - long_name: Store halfword - description: | - Store 16 bits of data from register `rs2` to an - address formed by adding `rs1` to a signed offset. - definedBy: I - assembly: xs2, imm(xs1) - encoding: - match: -----------------001-----0100011 - variables: - - name: imm - location: 31-25|11-7 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg virtual_address = X[rs1] + imm; +$schema: "inst_schema.json#" +kind: instruction +name: sh +long_name: Store halfword +description: | + Store 16 bits of data from register `rs2` to an + address formed by adding `rs1` to a signed offset. +definedBy: I +assembly: xs2, imm(xs1) +encoding: + match: -----------------001-----0100011 + variables: + - name: imm + location: 31-25|11-7 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg virtual_address = X[rs1] + imm; - write_memory<16>(virtual_address, X[rs2][15:0], $encoding); + write_memory<16>(virtual_address, X[rs2][15:0], $encoding); - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Write(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Write(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => { - let eares : MemoryOpResult(unit) = match width { - BYTE => mem_write_ea(paddr, 1, aq, rl, false), - HALF => mem_write_ea(paddr, 2, aq, rl, false), - WORD => mem_write_ea(paddr, 4, aq, rl, false), - DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let rs2_val = X(rs2); - let res : MemoryOpResult(bool) = match (width) { - BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), - HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), - WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), - DOUBLE if sizeof(xlen) >= 64 - => mem_write_value(paddr, 8, rs2_val, aq, rl, false), - _ => report_invalid_width(__FILE__, __LINE__, width, "store"), - }; - match (res) { - MemValue(true) => RETIRE_SUCCESS, - MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Write(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Write(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => { + let eares : MemoryOpResult(unit) = match width { + BYTE => mem_write_ea(paddr, 1, aq, rl, false), + HALF => mem_write_ea(paddr, 2, aq, rl, false), + WORD => mem_write_ea(paddr, 4, aq, rl, false), + DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let rs2_val = X(rs2); + let res : MemoryOpResult(bool) = match (width) { + BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), + HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), + WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), + DOUBLE if sizeof(xlen) >= 64 + => mem_write_value(paddr, 8, rs2_val, aq, rl, false), + _ => report_invalid_width(__FILE__, __LINE__, width, "store"), + }; + match (res) { + MemValue(true) => RETIRE_SUCCESS, + MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } } - } + } } - - + } + + diff --git a/arch/inst/I/sll.yaml b/arch/inst/I/sll.yaml index 3f48f4bc5..bdf68a0d2 100644 --- a/arch/inst/I/sll.yaml +++ b/arch/inst/I/sll.yaml @@ -1,61 +1,63 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sll: - long_name: Shift left logical - description: | - Shift the value in `rs1` left by the value in the lower 6 bits of `rs2`, and store the result in `rd`. - definedBy: I - assembly: xd, xs1, xs2 - encoding: - match: 0000000----------001-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (xlen() == 64) { - X[rd] = X[rs1] << X[rs2][5:0]; - } else { - X[rd] = X[rs1] << X[rs2][4:0]; - } - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sll +long_name: Shift left logical +description: | + Shift the value in `rs1` left by the value in the lower 6 bits of `rs2`, and store the result in `rd`. +definedBy: I +assembly: xd, xs1, xs2 +encoding: + match: 0000000----------001-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (xlen() == 64) { + X[rd] = X[rs1] << X[rs2][5:0]; + } else { + X[rd] = X[rs1] << X[rs2][4:0]; + } + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/slli.yaml b/arch/inst/I/slli.yaml index 3a378fdef..1a570568b 100644 --- a/arch/inst/I/slli.yaml +++ b/arch/inst/I/slli.yaml @@ -1,60 +1,62 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -slli: - long_name: Shift left logical immediate - description: Shift the value in rs1 left by shamt, and store the result in rd - definedBy: I - assembly: xd, xs1, shamt - encoding: - RV32: - match: 0000000----------001-----0010011 - variables: - - name: shamt - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - RV64: - match: 000000-----------001-----0010011 - variables: - - name: shamt - location: 25-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - # shamt is between 0-(XLEN-1) - X[rd] = X[rs1] << shamt; - - - - sail(): | - { - let rs1_val = X(rs1); - /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ - let result : xlenbits = match op { - RISCV_SLLI => if sizeof(xlen) == 32 - then rs1_val << shamt[4..0] - else rs1_val << shamt, - RISCV_SRLI => if sizeof(xlen) == 32 - then rs1_val >> shamt[4..0] - else rs1_val >> shamt, - RISCV_SRAI => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, shamt[4..0]) - else shift_right_arith64(rs1_val, shamt) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: slli +long_name: Shift left logical immediate +description: Shift the value in rs1 left by shamt, and store the result in rd +definedBy: I +assembly: xd, xs1, shamt +encoding: + RV32: + match: 0000000----------001-----0010011 + variables: + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 + RV64: + match: 000000-----------001-----0010011 + variables: + - name: shamt + location: 25-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + # shamt is between 0-(XLEN-1) + X[rd] = X[rs1] << shamt; + + + +sail(): | + { + let rs1_val = X(rs1); + /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ + let result : xlenbits = match op { + RISCV_SLLI => if sizeof(xlen) == 32 + then rs1_val << shamt[4..0] + else rs1_val << shamt, + RISCV_SRLI => if sizeof(xlen) == 32 + then rs1_val >> shamt[4..0] + else rs1_val >> shamt, + RISCV_SRAI => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, shamt[4..0]) + else shift_right_arith64(rs1_val, shamt) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/slliw.yaml b/arch/inst/I/slliw.yaml index 5e27f42ef..43b50fa90 100644 --- a/arch/inst/I/slliw.yaml +++ b/arch/inst/I/slliw.yaml @@ -1,44 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -slliw: - long_name: Shift left logical immediate word - description: Shift the 32-bit value in rs1 left by shamt, and store the sign-extended result in rd - definedBy: I - base: 64 - assembly: xd, xs1, shamt - encoding: - match: 0000000----------001-----0011011 - variables: - - name: shamt - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - # shamt is between 0-32 - X[rd] = sext(X[rs1] << shamt, 31); - - - - sail(): | - { - let rs1_val = (X(rs1))[31..0]; - let result : bits(32) = match op { - RISCV_SLLIW => rs1_val << shamt, - RISCV_SRLIW => rs1_val >> shamt, - RISCV_SRAIW => shift_right_arith32(rs1_val, shamt) - }; - X(rd) = sign_extend(result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: slliw +long_name: Shift left logical immediate word +description: Shift the 32-bit value in rs1 left by shamt, and store the sign-extended result in rd +definedBy: I +base: 64 +assembly: xd, xs1, shamt +encoding: + match: 0000000----------001-----0011011 + variables: + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + # shamt is between 0-32 + X[rd] = sext(X[rs1] << shamt, 31); + + + +sail(): | + { + let rs1_val = (X(rs1))[31..0]; + let result : bits(32) = match op { + RISCV_SLLIW => rs1_val << shamt, + RISCV_SRLIW => rs1_val >> shamt, + RISCV_SRAIW => shift_right_arith32(rs1_val, shamt) + }; + X(rd) = sign_extend(result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/sllw.yaml b/arch/inst/I/sllw.yaml index e526d6b0f..c745500f4 100644 --- a/arch/inst/I/sllw.yaml +++ b/arch/inst/I/sllw.yaml @@ -1,46 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sllw: - long_name: Shift left logical word - description: | - Shift the 32-bit value in `rs1` left by the value in the lower 5 bits of `rs2`, and store the sign-extended result in `rd`. - definedBy: I - base: 64 - assembly: xd, xs1, xs2 - encoding: - match: 0000000----------001-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): X[rd] = sext(X[rs1] << X[rs2][4:0], 31); - - - - sail(): | - { - let rs1_val = (X(rs1))[31..0]; - let rs2_val = (X(rs2))[31..0]; - let result : bits(32) = match op { - RISCV_ADDW => rs1_val + rs2_val, - RISCV_SUBW => rs1_val - rs2_val, - RISCV_SLLW => rs1_val << (rs2_val[4..0]), - RISCV_SRLW => rs1_val >> (rs2_val[4..0]), - RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) - }; - X(rd) = sign_extend(result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sllw +long_name: Shift left logical word +description: | + Shift the 32-bit value in `rs1` left by the value in the lower 5 bits of `rs2`, and store the sign-extended result in `rd`. +definedBy: I +base: 64 +assembly: xd, xs1, xs2 +encoding: + match: 0000000----------001-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): X[rd] = sext(X[rs1] << X[rs2][4:0], 31); + + + +sail(): | + { + let rs1_val = (X(rs1))[31..0]; + let rs2_val = (X(rs2))[31..0]; + let result : bits(32) = match op { + RISCV_ADDW => rs1_val + rs2_val, + RISCV_SUBW => rs1_val - rs2_val, + RISCV_SLLW => rs1_val << (rs2_val[4..0]), + RISCV_SRLW => rs1_val >> (rs2_val[4..0]), + RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) + }; + X(rd) = sign_extend(result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/slt.yaml b/arch/inst/I/slt.yaml index a991006d9..d66506891 100644 --- a/arch/inst/I/slt.yaml +++ b/arch/inst/I/slt.yaml @@ -1,61 +1,63 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -slt: - long_name: Set on less than - description: | - Places the value 1 in register `rd` if register `rs1` is less than the value in register `rs2`, where - both sources are treated as signed numbers, else 0 is written to `rd`. - definedBy: I - assembly: xd, xs1, rs2 - encoding: - match: 0000000----------010-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - XReg src1 = X[rs1]; - XReg src2 = X[rs2]; - - X[rd] = ($signed(src1) < $signed(src2)) ? '1 : '0; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: slt +long_name: Set on less than +description: | + Places the value 1 in register `rd` if register `rs1` is less than the value in register `rs2`, where + both sources are treated as signed numbers, else 0 is written to `rd`. +definedBy: I +assembly: xd, xs1, rs2 +encoding: + match: 0000000----------010-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + XReg src1 = X[rs1]; + XReg src2 = X[rs2]; + + X[rd] = ($signed(src1) < $signed(src2)) ? '1 : '0; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/slti.yaml b/arch/inst/I/slti.yaml index 29d9bed7c..5b6abcb17 100644 --- a/arch/inst/I/slti.yaml +++ b/arch/inst/I/slti.yaml @@ -1,48 +1,50 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -slti: - long_name: Set on less than immediate - description: | - Places the value 1 in register `rd` if register `rs1` is less than the sign-extended immediate - when both are treated as signed numbers, else 0 is written to `rd`. - definedBy: I - assembly: xd, xs1, imm - encoding: - match: -----------------010-----0010011 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - X[rd] = ($signed(X[rs1]) < $signed(imm)) ? '1 : '0; - - - - sail(): | - { - let rs1_val = X(rs1); - let immext : xlenbits = sign_extend(imm); - let result : xlenbits = match op { - RISCV_ADDI => rs1_val + immext, - RISCV_SLTI => zero_extend(bool_to_bits(rs1_val <_s immext)), - RISCV_SLTIU => zero_extend(bool_to_bits(rs1_val <_u immext)), - RISCV_ANDI => rs1_val & immext, - RISCV_ORI => rs1_val | immext, - RISCV_XORI => rs1_val ^ immext - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: slti +long_name: Set on less than immediate +description: | + Places the value 1 in register `rd` if register `rs1` is less than the sign-extended immediate + when both are treated as signed numbers, else 0 is written to `rd`. +definedBy: I +assembly: xd, xs1, imm +encoding: + match: -----------------010-----0010011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + X[rd] = ($signed(X[rs1]) < $signed(imm)) ? '1 : '0; + + + +sail(): | + { + let rs1_val = X(rs1); + let immext : xlenbits = sign_extend(imm); + let result : xlenbits = match op { + RISCV_ADDI => rs1_val + immext, + RISCV_SLTI => zero_extend(bool_to_bits(rs1_val <_s immext)), + RISCV_SLTIU => zero_extend(bool_to_bits(rs1_val <_u immext)), + RISCV_ANDI => rs1_val & immext, + RISCV_ORI => rs1_val | immext, + RISCV_XORI => rs1_val ^ immext + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/sltiu.yaml b/arch/inst/I/sltiu.yaml index 6a7cc4b4a..4981a7298 100644 --- a/arch/inst/I/sltiu.yaml +++ b/arch/inst/I/sltiu.yaml @@ -1,52 +1,54 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sltiu: - long_name: Set on less than immediate unsigned - description: | - Places the value 1 in register `rd` if register `rs1` is less than the sign-extended immediate - when both are treated as unsigned numbers (_i.e._, the immediate is first sign-extended to - XLEN bits then treated as an unsigned number), else 0 is written to `rd`. - - NOTE: `sltiu rd, rs1, 1` sets `rd` to 1 if `rs1` equals zero, otherwise sets `rd` to 0 - (assembler pseudoinstruction `SEQZ rd, rs`). - definedBy: I - assembly: xd, xs1, imm - encoding: - match: -----------------011-----0010011 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - X[rd] = (X[rs1] < imm) ? 1 : 0; - - - - sail(): | - { - let rs1_val = X(rs1); - let immext : xlenbits = sign_extend(imm); - let result : xlenbits = match op { - RISCV_ADDI => rs1_val + immext, - RISCV_SLTI => zero_extend(bool_to_bits(rs1_val <_s immext)), - RISCV_SLTIU => zero_extend(bool_to_bits(rs1_val <_u immext)), - RISCV_ANDI => rs1_val & immext, - RISCV_ORI => rs1_val | immext, - RISCV_XORI => rs1_val ^ immext - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sltiu +long_name: Set on less than immediate unsigned +description: | + Places the value 1 in register `rd` if register `rs1` is less than the sign-extended immediate + when both are treated as unsigned numbers (_i.e._, the immediate is first sign-extended to + XLEN bits then treated as an unsigned number), else 0 is written to `rd`. + + NOTE: `sltiu rd, rs1, 1` sets `rd` to 1 if `rs1` equals zero, otherwise sets `rd` to 0 + (assembler pseudoinstruction `SEQZ rd, rs`). +definedBy: I +assembly: xd, xs1, imm +encoding: + match: -----------------011-----0010011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + X[rd] = (X[rs1] < imm) ? 1 : 0; + + + +sail(): | + { + let rs1_val = X(rs1); + let immext : xlenbits = sign_extend(imm); + let result : xlenbits = match op { + RISCV_ADDI => rs1_val + immext, + RISCV_SLTI => zero_extend(bool_to_bits(rs1_val <_s immext)), + RISCV_SLTIU => zero_extend(bool_to_bits(rs1_val <_u immext)), + RISCV_ANDI => rs1_val & immext, + RISCV_ORI => rs1_val | immext, + RISCV_XORI => rs1_val ^ immext + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/sltu.yaml b/arch/inst/I/sltu.yaml index eff1b162e..c1ee3b10d 100644 --- a/arch/inst/I/sltu.yaml +++ b/arch/inst/I/sltu.yaml @@ -1,58 +1,60 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sltu: - long_name: Set on less than unsigned - description: | - Places the value 1 in register `rd` if register `rs1` is less than the value in register `rs2`, where - both sources are treated as unsigned numbers, else 0 is written to `rd`. - definedBy: I - assembly: xd, xs1, xs2 - encoding: - match: 0000000----------011-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - X[rd] = (X[rs1] < X[rs2]) ? 1 : 0; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sltu +long_name: Set on less than unsigned +description: | + Places the value 1 in register `rd` if register `rs1` is less than the value in register `rs2`, where + both sources are treated as unsigned numbers, else 0 is written to `rd`. +definedBy: I +assembly: xd, xs1, xs2 +encoding: + match: 0000000----------011-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + X[rd] = (X[rs1] < X[rs2]) ? 1 : 0; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/sra.yaml b/arch/inst/I/sra.yaml index b7a8b3efb..c088d33a2 100644 --- a/arch/inst/I/sra.yaml +++ b/arch/inst/I/sra.yaml @@ -1,61 +1,63 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sra: - long_name: Shift right arithmetic - description: | - Arithmetic shift the value in `rs1` right by the value in the lower 5 bits of `rs2`, and store the result in `rd`. - definedBy: I - assembly: xd, xs1, xs2 - encoding: - match: 0100000----------101-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (xlen() == 64) { - X[rd] = X[rs1] >>> X[rs2][5:0]; - } else { - X[rd] = X[rs1] >>> X[rs2][4:0]; - } - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sra +long_name: Shift right arithmetic +description: | + Arithmetic shift the value in `rs1` right by the value in the lower 5 bits of `rs2`, and store the result in `rd`. +definedBy: I +assembly: xd, xs1, xs2 +encoding: + match: 0100000----------101-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (xlen() == 64) { + X[rd] = X[rs1] >>> X[rs2][5:0]; + } else { + X[rd] = X[rs1] >>> X[rs2][4:0]; + } + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/srai.yaml b/arch/inst/I/srai.yaml index 81333fcf7..e749b3992 100644 --- a/arch/inst/I/srai.yaml +++ b/arch/inst/I/srai.yaml @@ -1,62 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -srai: - long_name: Shift right arithmetic immediate - description: | - Arithmetic shift (the original sign bit is copied into the vacated upper bits) the - value in rs1 right by shamt, and store the result in rd. - definedBy: I - assembly: xd, xs1, shamt - encoding: - RV32: - match: 0100000----------101-----0010011 - variables: - - name: shamt - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - RV64: - match: 010000-----------101-----0010011 - variables: - - name: shamt - location: 25-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - # shamt is between 0-63 - X[rd] = X[rs1] >>> shamt; - - - - sail(): | - { - let rs1_val = X(rs1); - /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ - let result : xlenbits = match op { - RISCV_SLLI => if sizeof(xlen) == 32 - then rs1_val << shamt[4..0] - else rs1_val << shamt, - RISCV_SRLI => if sizeof(xlen) == 32 - then rs1_val >> shamt[4..0] - else rs1_val >> shamt, - RISCV_SRAI => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, shamt[4..0]) - else shift_right_arith64(rs1_val, shamt) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: srai +long_name: Shift right arithmetic immediate +description: | + Arithmetic shift (the original sign bit is copied into the vacated upper bits) the + value in rs1 right by shamt, and store the result in rd. +definedBy: I +assembly: xd, xs1, shamt +encoding: + RV32: + match: 0100000----------101-----0010011 + variables: + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 + RV64: + match: 010000-----------101-----0010011 + variables: + - name: shamt + location: 25-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + # shamt is between 0-63 + X[rd] = X[rs1] >>> shamt; + + + +sail(): | + { + let rs1_val = X(rs1); + /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ + let result : xlenbits = match op { + RISCV_SLLI => if sizeof(xlen) == 32 + then rs1_val << shamt[4..0] + else rs1_val << shamt, + RISCV_SRLI => if sizeof(xlen) == 32 + then rs1_val >> shamt[4..0] + else rs1_val >> shamt, + RISCV_SRAI => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, shamt[4..0]) + else shift_right_arith64(rs1_val, shamt) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/sraiw.yaml b/arch/inst/I/sraiw.yaml index 490d9a6ab..feb39990c 100644 --- a/arch/inst/I/sraiw.yaml +++ b/arch/inst/I/sraiw.yaml @@ -1,47 +1,49 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sraiw: - long_name: Shift right arithmetic immediate word - description: | - Arithmetic shift (the original sign bit is copied into the vacated upper bits) the - 32-bit value in rs1 right by shamt, and store the sign-extended result in rd. - definedBy: I - base: 64 - assembly: xd, xs1, shamt - encoding: - match: 0100000----------101-----0011011 - variables: - - name: shamt - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - # shamt is between 0-32 - XReg operand = sext(X[rs1], 31); - X[rd] = sext(operand >>> shamt, 31); - - - - sail(): | - { - let rs1_val = (X(rs1))[31..0]; - let result : bits(32) = match op { - RISCV_SLLIW => rs1_val << shamt, - RISCV_SRLIW => rs1_val >> shamt, - RISCV_SRAIW => shift_right_arith32(rs1_val, shamt) - }; - X(rd) = sign_extend(result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sraiw +long_name: Shift right arithmetic immediate word +description: | + Arithmetic shift (the original sign bit is copied into the vacated upper bits) the + 32-bit value in rs1 right by shamt, and store the sign-extended result in rd. +definedBy: I +base: 64 +assembly: xd, xs1, shamt +encoding: + match: 0100000----------101-----0011011 + variables: + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + # shamt is between 0-32 + XReg operand = sext(X[rs1], 31); + X[rd] = sext(operand >>> shamt, 31); + + + +sail(): | + { + let rs1_val = (X(rs1))[31..0]; + let result : bits(32) = match op { + RISCV_SLLIW => rs1_val << shamt, + RISCV_SRLIW => rs1_val >> shamt, + RISCV_SRAIW => shift_right_arith32(rs1_val, shamt) + }; + X(rd) = sign_extend(result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/sraw.yaml b/arch/inst/I/sraw.yaml index 81ed8917b..f64645d96 100644 --- a/arch/inst/I/sraw.yaml +++ b/arch/inst/I/sraw.yaml @@ -1,49 +1,51 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sraw: - long_name: Shift right arithmetic word - description: | - Arithmetic shift the 32-bit value in `rs1` right by the value in the lower 5 bits of `rs2`, and store the sign-extended result in `rd`. - definedBy: I - base: 64 - assembly: xd, xs1, xs2 - encoding: - match: 0100000----------101-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - XReg operand1 = sext(X[rs1], 31); - - X[rd] = sext(operand1 >>> X[rs2][4:0], 31); - - - - sail(): | - { - let rs1_val = (X(rs1))[31..0]; - let rs2_val = (X(rs2))[31..0]; - let result : bits(32) = match op { - RISCV_ADDW => rs1_val + rs2_val, - RISCV_SUBW => rs1_val - rs2_val, - RISCV_SLLW => rs1_val << (rs2_val[4..0]), - RISCV_SRLW => rs1_val >> (rs2_val[4..0]), - RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) - }; - X(rd) = sign_extend(result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sraw +long_name: Shift right arithmetic word +description: | + Arithmetic shift the 32-bit value in `rs1` right by the value in the lower 5 bits of `rs2`, and store the sign-extended result in `rd`. +definedBy: I +base: 64 +assembly: xd, xs1, xs2 +encoding: + match: 0100000----------101-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + XReg operand1 = sext(X[rs1], 31); + + X[rd] = sext(operand1 >>> X[rs2][4:0], 31); + + + +sail(): | + { + let rs1_val = (X(rs1))[31..0]; + let rs2_val = (X(rs2))[31..0]; + let result : bits(32) = match op { + RISCV_ADDW => rs1_val + rs2_val, + RISCV_SUBW => rs1_val - rs2_val, + RISCV_SLLW => rs1_val << (rs2_val[4..0]), + RISCV_SRLW => rs1_val >> (rs2_val[4..0]), + RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) + }; + X(rd) = sign_extend(result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/srl.yaml b/arch/inst/I/srl.yaml index f83eb90a8..2ad1256d6 100644 --- a/arch/inst/I/srl.yaml +++ b/arch/inst/I/srl.yaml @@ -1,61 +1,63 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -srl: - long_name: Shift right logical - description: | - Logical shift the value in `rs1` right by the value in the lower bits of `rs2`, and store the result in `rd`. - definedBy: I - assembly: xd, xs1, xs2 - encoding: - match: 0000000----------101-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (xlen() == 64) { - X[rd] = X[rs1] >> X[rs2][5:0]; - } else { - X[rd] = X[rs1] >> X[rs2][4:0]; - } - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: srl +long_name: Shift right logical +description: | + Logical shift the value in `rs1` right by the value in the lower bits of `rs2`, and store the result in `rd`. +definedBy: I +assembly: xd, xs1, xs2 +encoding: + match: 0000000----------101-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (xlen() == 64) { + X[rd] = X[rs1] >> X[rs2][5:0]; + } else { + X[rd] = X[rs1] >> X[rs2][4:0]; + } + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/srli.yaml b/arch/inst/I/srli.yaml index 692859ed2..90a1904fa 100644 --- a/arch/inst/I/srli.yaml +++ b/arch/inst/I/srli.yaml @@ -1,59 +1,61 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -srli: - long_name: Shift right logical immediate - description: Shift the value in rs1 right by shamt, and store the result in rd - definedBy: I - assembly: xd, xs1, shamt - encoding: - RV32: - match: 0000000----------101-----0010011 - variables: - - name: shamt - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - RV64: - match: 000000-----------101-----0010011 - variables: - - name: shamt - location: 25-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - # shamt is between 0-63 - X[rd] = X[rs1] >> shamt; +$schema: "inst_schema.json#" +kind: instruction +name: srli +long_name: Shift right logical immediate +description: Shift the value in rs1 right by shamt, and store the result in rd +definedBy: I +assembly: xd, xs1, shamt +encoding: + RV32: + match: 0000000----------101-----0010011 + variables: + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 + RV64: + match: 000000-----------101-----0010011 + variables: + - name: shamt + location: 25-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + # shamt is between 0-63 + X[rd] = X[rs1] >> shamt; - sail(): | - { - let rs1_val = X(rs1); - /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ - let result : xlenbits = match op { - RISCV_SLLI => if sizeof(xlen) == 32 - then rs1_val << shamt[4..0] - else rs1_val << shamt, - RISCV_SRLI => if sizeof(xlen) == 32 - then rs1_val >> shamt[4..0] - else rs1_val >> shamt, - RISCV_SRAI => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, shamt[4..0]) - else shift_right_arith64(rs1_val, shamt) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +sail(): | + { + let rs1_val = X(rs1); + /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ + let result : xlenbits = match op { + RISCV_SLLI => if sizeof(xlen) == 32 + then rs1_val << shamt[4..0] + else rs1_val << shamt, + RISCV_SRLI => if sizeof(xlen) == 32 + then rs1_val >> shamt[4..0] + else rs1_val >> shamt, + RISCV_SRAI => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, shamt[4..0]) + else shift_right_arith64(rs1_val, shamt) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/srliw.yaml b/arch/inst/I/srliw.yaml index cc02beafe..f28912f01 100644 --- a/arch/inst/I/srliw.yaml +++ b/arch/inst/I/srliw.yaml @@ -1,46 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -srliw: - long_name: Shift right logical immediate word - description: Shift the 32-bit value in rs1 right by shamt, and store the sign-extended result in rd - definedBy: I - base: 64 - assembly: xd, xs1, shamt - encoding: - match: 0000000----------101-----0011011 - variables: - - name: shamt - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - # shamt is between 0-31 - XReg operand = X[rs1][31:0]; - - X[rd] = sext(operand >> shamt, 31); - - - - sail(): | - { - let rs1_val = (X(rs1))[31..0]; - let result : bits(32) = match op { - RISCV_SLLIW => rs1_val << shamt, - RISCV_SRLIW => rs1_val >> shamt, - RISCV_SRAIW => shift_right_arith32(rs1_val, shamt) - }; - X(rd) = sign_extend(result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: srliw +long_name: Shift right logical immediate word +description: Shift the 32-bit value in rs1 right by shamt, and store the sign-extended result in rd +definedBy: I +base: 64 +assembly: xd, xs1, shamt +encoding: + match: 0000000----------101-----0011011 + variables: + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + # shamt is between 0-31 + XReg operand = X[rs1][31:0]; + + X[rd] = sext(operand >> shamt, 31); + + + +sail(): | + { + let rs1_val = (X(rs1))[31..0]; + let result : bits(32) = match op { + RISCV_SLLIW => rs1_val << shamt, + RISCV_SRLIW => rs1_val >> shamt, + RISCV_SRAIW => shift_right_arith32(rs1_val, shamt) + }; + X(rd) = sign_extend(result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/srlw.yaml b/arch/inst/I/srlw.yaml index 2db8e984a..2df6b6721 100644 --- a/arch/inst/I/srlw.yaml +++ b/arch/inst/I/srlw.yaml @@ -1,46 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -srlw: - long_name: Shift right logical word - description: | - Logical shift the 32-bit value in `rs1` right by the value in the lower 5 bits of `rs2`, and store the sign-extended result in `rd`. - definedBy: I - base: 64 - assembly: xd, xs1, xs2 - encoding: - match: 0000000----------101-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): X[rd] = sext(X[rs1][31:0] >> X[rs2][4:0], 31); - - - - sail(): | - { - let rs1_val = (X(rs1))[31..0]; - let rs2_val = (X(rs2))[31..0]; - let result : bits(32) = match op { - RISCV_ADDW => rs1_val + rs2_val, - RISCV_SUBW => rs1_val - rs2_val, - RISCV_SLLW => rs1_val << (rs2_val[4..0]), - RISCV_SRLW => rs1_val >> (rs2_val[4..0]), - RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) - }; - X(rd) = sign_extend(result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: srlw +long_name: Shift right logical word +description: | + Logical shift the 32-bit value in `rs1` right by the value in the lower 5 bits of `rs2`, and store the sign-extended result in `rd`. +definedBy: I +base: 64 +assembly: xd, xs1, xs2 +encoding: + match: 0000000----------101-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): X[rd] = sext(X[rs1][31:0] >> X[rs2][4:0], 31); + + + +sail(): | + { + let rs1_val = (X(rs1))[31..0]; + let rs2_val = (X(rs2))[31..0]; + let result : bits(32) = match op { + RISCV_ADDW => rs1_val + rs2_val, + RISCV_SUBW => rs1_val - rs2_val, + RISCV_SLLW => rs1_val << (rs2_val[4..0]), + RISCV_SRLW => rs1_val >> (rs2_val[4..0]), + RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) + }; + X(rd) = sign_extend(result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/sub.yaml b/arch/inst/I/sub.yaml index ae5921a27..a031a7782 100644 --- a/arch/inst/I/sub.yaml +++ b/arch/inst/I/sub.yaml @@ -1,58 +1,60 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sub: - long_name: Subtract - description: Subtract the value in rs2 from rs1, and store the result in rd - definedBy: I - assembly: xd, xs1, xs2 - encoding: - match: 0100000----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - XReg t0 = X[rs1]; - XReg t1 = X[rs2]; - X[rd] = t0 - t1; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: sub +long_name: Subtract +description: Subtract the value in rs2 from rs1, and store the result in rd +definedBy: I +assembly: xd, xs1, xs2 +encoding: + match: 0100000----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + XReg t0 = X[rs1]; + XReg t1 = X[rs2]; + X[rd] = t0 - t1; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/subw.yaml b/arch/inst/I/subw.yaml index 54e0145d7..33d7354e0 100644 --- a/arch/inst/I/subw.yaml +++ b/arch/inst/I/subw.yaml @@ -1,48 +1,50 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -subw: - long_name: Subtract word - description: Subtract the 32-bit values in rs2 from rs1, and store the sign-extended result in rd - definedBy: I - base: 64 - assembly: xd, xs1, xs2 - encoding: - match: 0100000----------000-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - Bits<32> t0 = X[rs1][31:0]; - Bits<32> t1 = X[rs2][31:0]; - X[rd] = sext(t0 - t1, 31); - - - - sail(): | - { - let rs1_val = (X(rs1))[31..0]; - let rs2_val = (X(rs2))[31..0]; - let result : bits(32) = match op { - RISCV_ADDW => rs1_val + rs2_val, - RISCV_SUBW => rs1_val - rs2_val, - RISCV_SLLW => rs1_val << (rs2_val[4..0]), - RISCV_SRLW => rs1_val >> (rs2_val[4..0]), - RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) - }; - X(rd) = sign_extend(result); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: subw +long_name: Subtract word +description: Subtract the 32-bit values in rs2 from rs1, and store the sign-extended result in rd +definedBy: I +base: 64 +assembly: xd, xs1, xs2 +encoding: + match: 0100000----------000-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + Bits<32> t0 = X[rs1][31:0]; + Bits<32> t1 = X[rs2][31:0]; + X[rd] = sext(t0 - t1, 31); + + + +sail(): | + { + let rs1_val = (X(rs1))[31..0]; + let rs2_val = (X(rs2))[31..0]; + let result : bits(32) = match op { + RISCV_ADDW => rs1_val + rs2_val, + RISCV_SUBW => rs1_val - rs2_val, + RISCV_SLLW => rs1_val << (rs2_val[4..0]), + RISCV_SRLW => rs1_val >> (rs2_val[4..0]), + RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) + }; + X(rd) = sign_extend(result); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/sw.yaml b/arch/inst/I/sw.yaml index d94501a82..135995c75 100644 --- a/arch/inst/I/sw.yaml +++ b/arch/inst/I/sw.yaml @@ -1,76 +1,78 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sw: - long_name: Store word - description: | - Store 32 bits of data from register `rs2` to an - address formed by adding `rs1` to a signed offset. - definedBy: I - assembly: xs2, imm(xs1) - encoding: - match: -----------------010-----0100011 - variables: - - name: imm - location: 31-25|11-7 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - operation(): | - XReg virtual_address = X[rs1] + imm; +$schema: "inst_schema.json#" +kind: instruction +name: sw +long_name: Store word +description: | + Store 32 bits of data from register `rs2` to an + address formed by adding `rs1` to a signed offset. +definedBy: I +assembly: xs2, imm(xs1) +encoding: + match: -----------------010-----0100011 + variables: + - name: imm + location: 31-25|11-7 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +operation(): | + XReg virtual_address = X[rs1] + imm; - write_memory<32>(virtual_address, X[rs2][31:0], $encoding); + write_memory<32>(virtual_address, X[rs2][31:0], $encoding); - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Write(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Write(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => { - let eares : MemoryOpResult(unit) = match width { - BYTE => mem_write_ea(paddr, 1, aq, rl, false), - HALF => mem_write_ea(paddr, 2, aq, rl, false), - WORD => mem_write_ea(paddr, 4, aq, rl, false), - DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let rs2_val = X(rs2); - let res : MemoryOpResult(bool) = match (width) { - BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), - HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), - WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), - DOUBLE if sizeof(xlen) >= 64 - => mem_write_value(paddr, 8, rs2_val, aq, rl, false), - _ => report_invalid_width(__FILE__, __LINE__, width, "store"), - }; - match (res) { - MemValue(true) => RETIRE_SUCCESS, - MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Write(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Write(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => { + let eares : MemoryOpResult(unit) = match width { + BYTE => mem_write_ea(paddr, 1, aq, rl, false), + HALF => mem_write_ea(paddr, 2, aq, rl, false), + WORD => mem_write_ea(paddr, 4, aq, rl, false), + DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let rs2_val = X(rs2); + let res : MemoryOpResult(bool) = match (width) { + BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), + HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), + WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), + DOUBLE if sizeof(xlen) >= 64 + => mem_write_value(paddr, 8, rs2_val, aq, rl, false), + _ => report_invalid_width(__FILE__, __LINE__, width, "store"), + }; + match (res) { + MemValue(true) => RETIRE_SUCCESS, + MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } } - } + } } - - + } + + diff --git a/arch/inst/I/wfi.yaml b/arch/inst/I/wfi.yaml index f337fbeb8..0eabdcc63 100644 --- a/arch/inst/I/wfi.yaml +++ b/arch/inst/I/wfi.yaml @@ -1,125 +1,127 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -wfi: - long_name: Wait for interrupt - description: | - Can causes the processor to enter a low-power state until the next interrupt occurs. - - <%- if ext?(:H) -%> - The behavior of `wfi` is affected by the `mstatus.TW` - and `hstatus.VTW` bits, as summarized below. - - [%autowidth,%footer] - |=== - .2+| [.rotate]#`mstatus.TW`# .2+| [.rotate]#`hstatus.VTW`# 4+^.>| `wfi` behavior - h| HS-mode h| U-mode h| VS-mode h| in VU-mode - - | 0 | 0 | Wait | Trap (I) | Wait | Trap (V) - | 0 | 1 | Wait | Trap (I) | Trap (V) | Trap (V) - | 1 | - | Trap (I) | Trap (I) | Trap (I) | Trap (I) - - 6+| Trap (I) - Trap with `Illegal Instruction` code + - Trap (V) - Trap with `Virtual Instruction` code - |=== - - <%- else -%> - The `wfi` instruction is also affected by `mstatus.TW`, as shown below: - - [%autowidth,%footer] - |=== - .2+| [.rotate]#`mstatus.TW`# 2+^.>| `wfi` behavior - h| S-mode h| U-mode - - | 0 | Wait | Trap (I) - | 1 | Trap (I) | Trap (I) - - 3+| Trap (I) - Trap with `Illegal Instruction` code - |=== - - <%- end -%> - - When `wfi` is marked as causing a trap above, the implementation is allowed to wait - for an unspecified period of time to see if an interrupt occurs before raising the trap. - That period of time can be zero (_i.e._, `wfi` always causes a trap in the cases identified - above). - definedBy: Sm - assembly: "" - encoding: - match: '00010000010100000000000001110011' - access: - s: sometimes - u: sometimes - vs: sometimes - vu: sometimes - access_detail: | - <%- if ext?(:H) -%> - The behavior of `wfi` is affected by the `mstatus.TW` - and `hstatus.VTW` bits, as summarized below. - - [%autowidth,%footer] - |=== - .2+| [.rotate]#`mstatus.TW`# .2+| [.rotate]#`hstatus.VTW`# 4+^.>| `wfi` behavior - h| HS-mode h| U-mode h| VS-mode h| in VU-mode - - | 0 | 0 | Wait | Trap (I) | Wait | Trap (V) - | 0 | 1 | Wait | Trap (I) | Trap (V) | Trap (V) - | 1 | - | Trap (I) | Trap (I) | Trap (I) | Trap (I) - - 6+| Trap (I) - Trap with `Illegal Instruction` code + - Trap (V) - Trap with `Virtual Instruction` code - |=== - - <%- else -%> - The `wfi` instruction is also affected by `mstatus.TW`, as shown below: - - [%autowidth,%footer] - |=== - .2+| [.rotate]#`mstatus.TW`# 2+^.>| `wfi` behavior - h| S-mode h| U-mode - - | 0 | Wait | Trap (I) - | 1 | Trap (I) | Trap (I) - - 3+| Trap (I) - Trap with `Illegal Instruction` code - |=== - - <%- end -%> - operation(): | - # first, perform all the access checks - if (mode() == PrivilegeMode::U) { +$schema: "inst_schema.json#" +kind: instruction +name: wfi +long_name: Wait for interrupt +description: | + Can causes the processor to enter a low-power state until the next interrupt occurs. + + <%- if ext?(:H) -%> + The behavior of `wfi` is affected by the `mstatus.TW` + and `hstatus.VTW` bits, as summarized below. + + [%autowidth,%footer] + |=== + .2+| [.rotate]#`mstatus.TW`# .2+| [.rotate]#`hstatus.VTW`# 4+^.>| `wfi` behavior + h| HS-mode h| U-mode h| VS-mode h| in VU-mode + + | 0 | 0 | Wait | Trap (I) | Wait | Trap (V) + | 0 | 1 | Wait | Trap (I) | Trap (V) | Trap (V) + | 1 | - | Trap (I) | Trap (I) | Trap (I) | Trap (I) + + 6+| Trap (I) - Trap with `Illegal Instruction` code + + Trap (V) - Trap with `Virtual Instruction` code + |=== + + <%- else -%> + The `wfi` instruction is also affected by `mstatus.TW`, as shown below: + + [%autowidth,%footer] + |=== + .2+| [.rotate]#`mstatus.TW`# 2+^.>| `wfi` behavior + h| S-mode h| U-mode + + | 0 | Wait | Trap (I) + | 1 | Trap (I) | Trap (I) + + 3+| Trap (I) - Trap with `Illegal Instruction` code + |=== + + <%- end -%> + + When `wfi` is marked as causing a trap above, the implementation is allowed to wait + for an unspecified period of time to see if an interrupt occurs before raising the trap. + That period of time can be zero (_i.e._, `wfi` always causes a trap in the cases identified + above). +definedBy: Sm +assembly: "" +encoding: + match: '00010000010100000000000001110011' +access: + s: sometimes + u: sometimes + vs: sometimes + vu: sometimes +access_detail: | + <%- if ext?(:H) -%> + The behavior of `wfi` is affected by the `mstatus.TW` + and `hstatus.VTW` bits, as summarized below. + + [%autowidth,%footer] + |=== + .2+| [.rotate]#`mstatus.TW`# .2+| [.rotate]#`hstatus.VTW`# 4+^.>| `wfi` behavior + h| HS-mode h| U-mode h| VS-mode h| in VU-mode + + | 0 | 0 | Wait | Trap (I) | Wait | Trap (V) + | 0 | 1 | Wait | Trap (I) | Trap (V) | Trap (V) + | 1 | - | Trap (I) | Trap (I) | Trap (I) | Trap (I) + + 6+| Trap (I) - Trap with `Illegal Instruction` code + + Trap (V) - Trap with `Virtual Instruction` code + |=== + + <%- else -%> + The `wfi` instruction is also affected by `mstatus.TW`, as shown below: + + [%autowidth,%footer] + |=== + .2+| [.rotate]#`mstatus.TW`# 2+^.>| `wfi` behavior + h| S-mode h| U-mode + + | 0 | Wait | Trap (I) + | 1 | Trap (I) | Trap (I) + + 3+| Trap (I) - Trap with `Illegal Instruction` code + |=== + + <%- end -%> +operation(): | + # first, perform all the access checks + if (mode() == PrivilegeMode::U) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if ((CSR[misa].S == 1) && (CSR[mstatus].TW == 1'b1)) { + if (mode() != PrivilegeMode::M) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } - if ((CSR[misa].S == 1) && (CSR[mstatus].TW == 1'b1)) { - if (mode() != PrivilegeMode::M) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (CSR[misa].H == 1) { + if (CSR[hstatus].VTW == 1'b0) { + if (mode() == PrivilegeMode::VU) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); } - } - if (CSR[misa].H == 1) { - if (CSR[hstatus].VTW == 1'b0) { - if (mode() == PrivilegeMode::VU) { - raise (ExceptionCode::VirtualInstruction, mode(), $encoding); - } - } else if (CSR[hstatus].VTW == 1'b1) { - if ((mode() == PrivilegeMode::VS) || (mode() == PrivilegeMode::VU)) { - raise (ExceptionCode::VirtualInstruction, mode(), $encoding); - } + } else if (CSR[hstatus].VTW == 1'b1) { + if ((mode() == PrivilegeMode::VS) || (mode() == PrivilegeMode::VU)) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); } } + } - # passed, so now do the wait - wfi(); + # passed, so now do the wait + wfi(); - sail(): | - match cur_privilege { - Machine => { platform_wfi(); RETIRE_SUCCESS }, - Supervisor => if mstatus.TW() == 0b1 - then { handle_illegal(); RETIRE_FAIL } - else { platform_wfi(); RETIRE_SUCCESS }, - User => { handle_illegal(); RETIRE_FAIL } - } - - +sail(): | + match cur_privilege { + Machine => { platform_wfi(); RETIRE_SUCCESS }, + Supervisor => if mstatus.TW() == 0b1 + then { handle_illegal(); RETIRE_FAIL } + else { platform_wfi(); RETIRE_SUCCESS }, + User => { handle_illegal(); RETIRE_FAIL } + } + + diff --git a/arch/inst/I/xor.yaml b/arch/inst/I/xor.yaml index 22f83318c..cec0aa761 100644 --- a/arch/inst/I/xor.yaml +++ b/arch/inst/I/xor.yaml @@ -1,55 +1,57 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -xor: - long_name: Exclusive Or - description: Exclusive or rs1 with rs2, and store the result in rd - definedBy: I - assembly: xd, xs1, xs2 - encoding: - match: 0000000----------100-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): X[rd] = X[rs1] ^ X[rs2]; - - - - sail(): | - { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let result : xlenbits = match op { - RISCV_ADD => rs1_val + rs2_val, - RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), - RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), - RISCV_AND => rs1_val & rs2_val, - RISCV_OR => rs1_val | rs2_val, - RISCV_XOR => rs1_val ^ rs2_val, - RISCV_SLL => if sizeof(xlen) == 32 - then rs1_val << (rs2_val[4..0]) - else rs1_val << (rs2_val[5..0]), - RISCV_SRL => if sizeof(xlen) == 32 - then rs1_val >> (rs2_val[4..0]) - else rs1_val >> (rs2_val[5..0]), - RISCV_SUB => rs1_val - rs2_val, - RISCV_SRA => if sizeof(xlen) == 32 - then shift_right_arith32(rs1_val, rs2_val[4..0]) - else shift_right_arith64(rs1_val, rs2_val[5..0]) - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: xor +long_name: Exclusive Or +description: Exclusive or rs1 with rs2, and store the result in rd +definedBy: I +assembly: xd, xs1, xs2 +encoding: + match: 0000000----------100-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): X[rd] = X[rs1] ^ X[rs2]; + + + +sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/I/xori.yaml b/arch/inst/I/xori.yaml index 655bea5b8..169f3dfa3 100644 --- a/arch/inst/I/xori.yaml +++ b/arch/inst/I/xori.yaml @@ -1,45 +1,47 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -xori: - long_name: Exclusive Or immediate - description: Exclusive or an immediate to the value in rs1, and store the result in rd - definedBy: I - assembly: xd, xs1, imm - encoding: - match: -----------------100-----0010011 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): X[rd] = X[rs1] ^ imm; - - - - sail(): | - { - let rs1_val = X(rs1); - let immext : xlenbits = sign_extend(imm); - let result : xlenbits = match op { - RISCV_ADDI => rs1_val + immext, - RISCV_SLTI => zero_extend(bool_to_bits(rs1_val <_s immext)), - RISCV_SLTIU => zero_extend(bool_to_bits(rs1_val <_u immext)), - RISCV_ANDI => rs1_val & immext, - RISCV_ORI => rs1_val | immext, - RISCV_XORI => rs1_val ^ immext - }; - X(rd) = result; - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: xori +long_name: Exclusive Or immediate +description: Exclusive or an immediate to the value in rs1, and store the result in rd +definedBy: I +assembly: xd, xs1, imm +encoding: + match: -----------------100-----0010011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): X[rd] = X[rs1] ^ imm; + + + +sail(): | + { + let rs1_val = X(rs1); + let immext : xlenbits = sign_extend(imm); + let result : xlenbits = match op { + RISCV_ADDI => rs1_val + immext, + RISCV_SLTI => zero_extend(bool_to_bits(rs1_val <_s immext)), + RISCV_SLTIU => zero_extend(bool_to_bits(rs1_val <_u immext)), + RISCV_ANDI => rs1_val & immext, + RISCV_ORI => rs1_val | immext, + RISCV_XORI => rs1_val ^ immext + }; + X(rd) = result; + RETIRE_SUCCESS + } + + diff --git a/arch/inst/M/div.yaml b/arch/inst/M/div.yaml index c1e08f4f6..ebe7d999c 100644 --- a/arch/inst/M/div.yaml +++ b/arch/inst/M/div.yaml @@ -1,72 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -div: - long_name: Signed division - description: | - Divide rs1 by rs2, and store the result in rd. The remainder is discarded. +$schema: "inst_schema.json#" +kind: instruction +name: div +long_name: Signed division +description: | + Divide rs1 by rs2, and store the result in rd. The remainder is discarded. - Division by zero will put -1 into rd. - - Division resulting in signed overflow (when most negative number is divided by -1) - will put the most negative number into rd; - definedBy: M - assembly: xd, xs1, xs2 - encoding: - match: 0000001----------100-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + Division by zero will put -1 into rd. + + Division resulting in signed overflow (when most negative number is divided by -1) + will put the most negative number into rd; +definedBy: M +assembly: xd, xs1, xs2 +encoding: + match: 0000001----------100-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg src1 = X[rs1]; + XReg src2 = X[rs2]; + + if (src2 == 0) { + # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined + # to be -1 + X[rd] = {XLEN{1'b1}}; - XReg src1 = X[rs1]; - XReg src2 = X[rs2]; + } else if ((src1 == {1'b1, {XLEN-1{1'b0}}}) && (src2 == {XLEN{1'b1}})) { + # signed overflow. Since RISC-V does not have arithmetic exceptions, the result is defined + # to be the most negative number (-2^(XLEN-1)) + X[rd] = {1'b1, {XLEN-1{1'b0}}}; - if (src2 == 0) { - # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined - # to be -1 - X[rd] = {XLEN{1'b1}}; + } else { + # no special case, just divide + X[rd] = $signed(src1) / $signed(src2); + } - } else if ((src1 == {1'b1, {XLEN-1{1'b0}}}) && (src2 == {XLEN{1'b1}})) { - # signed overflow. Since RISC-V does not have arithmetic exceptions, the result is defined - # to be the most negative number (-2^(XLEN-1)) - X[rd] = {1'b1, {XLEN-1{1'b0}}}; +sail(): | + { + if extension("M") then { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); + let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); + let q : int = if rs2_int == 0 then -1 else quot_round_zero(rs1_int, rs2_int); + /* check for signed overflow */ + let q': int = if s & q > xlen_max_signed then xlen_min_signed else q; + X(rd) = to_bits(sizeof(xlen), q'); + RETIRE_SUCCESS } else { - # no special case, just divide - X[rd] = $signed(src1) / $signed(src2); + handle_illegal(); + RETIRE_FAIL } + } - sail(): | - { - if extension("M") then { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); - let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); - let q : int = if rs2_int == 0 then -1 else quot_round_zero(rs1_int, rs2_int); - /* check for signed overflow */ - let q': int = if s & q > xlen_max_signed then xlen_min_signed else q; - X(rd) = to_bits(sizeof(xlen), q'); - RETIRE_SUCCESS - } else { - handle_illegal(); - RETIRE_FAIL - } - } - - diff --git a/arch/inst/M/divu.yaml b/arch/inst/M/divu.yaml index 7cdb7718b..0e0543cb6 100644 --- a/arch/inst/M/divu.yaml +++ b/arch/inst/M/divu.yaml @@ -1,64 +1,66 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -divu: - long_name: Unsigned division - description: | - Divide unsigned values in rs1 by rs2, and store the result in rd. - - The remainder is discarded. +$schema: "inst_schema.json#" +kind: instruction +name: divu +long_name: Unsigned division +description: | + Divide unsigned values in rs1 by rs2, and store the result in rd. + + The remainder is discarded. - If the value in rs2 is zero, rd gets the largest unsigned value. - definedBy: M - assembly: xd, xs1, xs2 - encoding: - match: 0000001----------101-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + If the value in rs2 is zero, rd gets the largest unsigned value. +definedBy: M +assembly: xd, xs1, xs2 +encoding: + match: 0000001----------101-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg src1 = X[rs1]; + XReg src2 = X[rs2]; + + if (src2 == 0) { + # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined + # to be -1 + X[rd] = {XLEN{1'b1}}; + } else { + X[rd] = src1 / src2; + } - XReg src1 = X[rs1]; - XReg src2 = X[rs2]; - if (src2 == 0) { - # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined - # to be -1 - X[rd] = {XLEN{1'b1}}; +sail(): | + { + if extension("M") then { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); + let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); + let q : int = if rs2_int == 0 then -1 else quot_round_zero(rs1_int, rs2_int); + /* check for signed overflow */ + let q': int = if s & q > xlen_max_signed then xlen_min_signed else q; + X(rd) = to_bits(sizeof(xlen), q'); + RETIRE_SUCCESS } else { - X[rd] = src1 / src2; + handle_illegal(); + RETIRE_FAIL } + } - sail(): | - { - if extension("M") then { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); - let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); - let q : int = if rs2_int == 0 then -1 else quot_round_zero(rs1_int, rs2_int); - /* check for signed overflow */ - let q': int = if s & q > xlen_max_signed then xlen_min_signed else q; - X(rd) = to_bits(sizeof(xlen), q'); - RETIRE_SUCCESS - } else { - handle_illegal(); - RETIRE_FAIL - } - } - - diff --git a/arch/inst/M/divuw.yaml b/arch/inst/M/divuw.yaml index df01adba3..693d89a5a 100644 --- a/arch/inst/M/divuw.yaml +++ b/arch/inst/M/divuw.yaml @@ -1,70 +1,72 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -divuw: - long_name: Unsigned 32-bit division - description: | - Divide the unsigned 32-bit values in rs1 and rs2, and store the sign-extended result in rd. - - The remainder is discarded. +$schema: "inst_schema.json#" +kind: instruction +name: divuw +long_name: Unsigned 32-bit division +description: | + Divide the unsigned 32-bit values in rs1 and rs2, and store the sign-extended result in rd. + + The remainder is discarded. - If the value in rs2 is zero, rd is written with all 1s. - definedBy: M - assembly: xd, xs1, xs2 - encoding: - match: 0000001----------101-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + If the value in rs2 is zero, rd is written with all 1s. +definedBy: M +assembly: xd, xs1, xs2 +encoding: + match: 0000001----------101-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - Bits<32> src1 = X[rs1][31:0]; - Bits<32> src2 = X[rs2][31:0]; + Bits<32> src1 = X[rs1][31:0]; + Bits<32> src2 = X[rs2][31:0]; - if (src2 == 0) { - # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined - # to be the largest 32-bit unsigned value (sign extended to 64-bits) - X[rd] = {64{1'b1}}; + if (src2 == 0) { + # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined + # to be the largest 32-bit unsigned value (sign extended to 64-bits) + X[rd] = {64{1'b1}}; - } else { + } else { - Bits<32> result = src1 / src2; - Bits<1> sign_bit = result[31]; + Bits<32> result = src1 / src2; + Bits<1> sign_bit = result[31]; - X[rd] = {{32{sign_bit}}, result}; - } + X[rd] = {{32{sign_bit}}, result}; + } - sail(): | - { - if extension("M") then { - let rs1_val = X(rs1)[31..0]; - let rs2_val = X(rs2)[31..0]; - let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); - let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); - let q : int = if rs2_int == 0 then -1 else quot_round_zero(rs1_int, rs2_int); - /* check for signed overflow */ - let q': int = if s & q > (2 ^ 31 - 1) then (0 - 2^31) else q; - X(rd) = sign_extend(to_bits(32, q')); - RETIRE_SUCCESS - } else { - handle_illegal(); - RETIRE_FAIL - } +sail(): | + { + if extension("M") then { + let rs1_val = X(rs1)[31..0]; + let rs2_val = X(rs2)[31..0]; + let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); + let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); + let q : int = if rs2_int == 0 then -1 else quot_round_zero(rs1_int, rs2_int); + /* check for signed overflow */ + let q': int = if s & q > (2 ^ 31 - 1) then (0 - 2^31) else q; + X(rd) = sign_extend(to_bits(32, q')); + RETIRE_SUCCESS + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/M/divw.yaml b/arch/inst/M/divw.yaml index 62b6636d8..70b3517be 100644 --- a/arch/inst/M/divw.yaml +++ b/arch/inst/M/divw.yaml @@ -1,79 +1,81 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -divw: - long_name: Signed 32-bit division - description: | - Divide the lower 32-bits of register rs1 by the lower 32-bits of register rs2, - and store the sign-extended result in rd. - - The remainder is discarded. +$schema: "inst_schema.json#" +kind: instruction +name: divw +long_name: Signed 32-bit division +description: | + Divide the lower 32-bits of register rs1 by the lower 32-bits of register rs2, + and store the sign-extended result in rd. + + The remainder is discarded. - Division by zero will put -1 into rd. - - Division resulting in signed overflow (when most negative number is divided by -1) - will put the most negative number into rd; - definedBy: M - assembly: xd, xs1, xs2 - encoding: - match: 0000001----------100-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + Division by zero will put -1 into rd. + + Division resulting in signed overflow (when most negative number is divided by -1) + will put the most negative number into rd; +definedBy: M +assembly: xd, xs1, xs2 +encoding: + match: 0000001----------100-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - Bits<32> src1 = X[rs1][31:0]; - Bits<32> src2 = X[rs2][31:0]; + Bits<32> src1 = X[rs1][31:0]; + Bits<32> src2 = X[rs2][31:0]; - if (src2 == 0) { - # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined - # to be -1 - X[rd] = {XLEN{1'b1}}; + if (src2 == 0) { + # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined + # to be -1 + X[rd] = {XLEN{1'b1}}; - } else if ((src1 == {33'b1, 31'b0}) && (src2 == 32'b1)) { - # signed overflow. Since RISC-V does not have arithmetic exceptions, the result is defined - # to be the most negative number (-2^(31)) - X[rd] = {33'b1, 31'b0}; + } else if ((src1 == {33'b1, 31'b0}) && (src2 == 32'b1)) { + # signed overflow. Since RISC-V does not have arithmetic exceptions, the result is defined + # to be the most negative number (-2^(31)) + X[rd] = {33'b1, 31'b0}; - } else { - # no special case, just divide - Bits<32> result = $signed(src1) / $signed(src2); - Bits<1> sign_bit = result[31]; + } else { + # no special case, just divide + Bits<32> result = $signed(src1) / $signed(src2); + Bits<1> sign_bit = result[31]; - X[rd] = {{32{sign_bit}}, result}; - } + X[rd] = {{32{sign_bit}}, result}; + } - sail(): | - { - if extension("M") then { - let rs1_val = X(rs1)[31..0]; - let rs2_val = X(rs2)[31..0]; - let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); - let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); - let q : int = if rs2_int == 0 then -1 else quot_round_zero(rs1_int, rs2_int); - /* check for signed overflow */ - let q': int = if s & q > (2 ^ 31 - 1) then (0 - 2^31) else q; - X(rd) = sign_extend(to_bits(32, q')); - RETIRE_SUCCESS - } else { - handle_illegal(); - RETIRE_FAIL - } +sail(): | + { + if extension("M") then { + let rs1_val = X(rs1)[31..0]; + let rs2_val = X(rs2)[31..0]; + let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); + let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); + let q : int = if rs2_int == 0 then -1 else quot_round_zero(rs1_int, rs2_int); + /* check for signed overflow */ + let q': int = if s & q > (2 ^ 31 - 1) then (0 - 2^31) else q; + X(rd) = sign_extend(to_bits(32, q')); + RETIRE_SUCCESS + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/M/mul.yaml b/arch/inst/M/mul.yaml index 007d1aa1d..b8624a008 100644 --- a/arch/inst/M/mul.yaml +++ b/arch/inst/M/mul.yaml @@ -1,68 +1,70 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -mul: - long_name: Signed multiply - description: | - MUL performs an XLEN-bitxXLEN-bit multiplication of `rs1` by `rs2` and places the lower - XLEN bits in the destination register. - Any overflow is thrown away. +$schema: "inst_schema.json#" +kind: instruction +name: mul +long_name: Signed multiply +description: | + MUL performs an XLEN-bitxXLEN-bit multiplication of `rs1` by `rs2` and places the lower + XLEN bits in the destination register. + Any overflow is thrown away. - [NOTE] - If both the high and low bits of the same product are required, then the recommended code - sequence is: - MULH[[S]U] rdh, rs1, rs2; MUL rdl, rs1, rs2 - (source register specifiers must be in same order and rdh cannot be the same as rs1 or rs2). - Microarchitectures can then fuse these into a single multiply operation instead of - performing two separate multiplies. + [NOTE] + If both the high and low bits of the same product are required, then the recommended code + sequence is: + MULH[[S]U] rdh, rs1, rs2; MUL rdl, rs1, rs2 + (source register specifiers must be in same order and rdh cannot be the same as rs1 or rs2). + Microarchitectures can then fuse these into a single multiply operation instead of + performing two separate multiplies. - definedBy: - anyOf: [M, Zmmul] - assembly: xd, xs1, xs2 - encoding: - match: 0000001----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +definedBy: + anyOf: [M, Zmmul] +assembly: xd, xs1, xs2 +encoding: + match: 0000001----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - XReg src1 = X[rs1]; - XReg src2 = X[rs2]; + XReg src1 = X[rs1]; + XReg src2 = X[rs2]; - X[rd] = (src1 * src2)[XLEN-1:0]; + X[rd] = (src1 * src2)[XLEN-1:0]; - sail(): | - { - if extension("M") | haveZmmul() then { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let rs1_int : int = if signed1 then signed(rs1_val) else unsigned(rs1_val); - let rs2_int : int = if signed2 then signed(rs2_val) else unsigned(rs2_val); - let result_wide = to_bits(2 * sizeof(xlen), rs1_int * rs2_int); - let result = if high - then result_wide[(2 * sizeof(xlen) - 1) .. sizeof(xlen)] - else result_wide[(sizeof(xlen) - 1) .. 0]; - X(rd) = result; - RETIRE_SUCCESS - } else { - handle_illegal(); - RETIRE_FAIL - } +sail(): | + { + if extension("M") | haveZmmul() then { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let rs1_int : int = if signed1 then signed(rs1_val) else unsigned(rs1_val); + let rs2_int : int = if signed2 then signed(rs2_val) else unsigned(rs2_val); + let result_wide = to_bits(2 * sizeof(xlen), rs1_int * rs2_int); + let result = if high + then result_wide[(2 * sizeof(xlen) - 1) .. sizeof(xlen)] + else result_wide[(sizeof(xlen) - 1) .. 0]; + X(rd) = result; + RETIRE_SUCCESS + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/M/mulh.yaml b/arch/inst/M/mulh.yaml index afca2345a..77921b4f0 100644 --- a/arch/inst/M/mulh.yaml +++ b/arch/inst/M/mulh.yaml @@ -1,73 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -mulh: - long_name: Signed multiply high - description: | - Multiply the signed values in rs1 to rs2, and store the upper half of the result in rd. - The lower half is thrown away. +$schema: "inst_schema.json#" +kind: instruction +name: mulh +long_name: Signed multiply high +description: | + Multiply the signed values in rs1 to rs2, and store the upper half of the result in rd. + The lower half is thrown away. - If both the upper and lower halves are needed, it suggested to use the sequence: + If both the upper and lower halves are needed, it suggested to use the sequence: - --- - mulh rdh, rs1, rs2 - mul rdl, rs1, rs2 - --- + --- + mulh rdh, rs1, rs2 + mul rdl, rs1, rs2 + --- - Microarchitectures may look for that sequence and fuse the operations. - definedBy: - anyOf: [M, Zmmul] - assembly: xd, xs1, xs2 - encoding: - match: 0000001----------001-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + Microarchitectures may look for that sequence and fuse the operations. +definedBy: + anyOf: [M, Zmmul] +assembly: xd, xs1, xs2 +encoding: + match: 0000001----------001-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - # enlarge and sign extend the sources - Bits<1> rs1_sign_bit = X[rs1][xlen()-1]; - Bits src1 = {{xlen(){rs1_sign_bit}}, X[rs1]}; + # enlarge and sign extend the sources + Bits<1> rs1_sign_bit = X[rs1][xlen()-1]; + Bits src1 = {{xlen(){rs1_sign_bit}}, X[rs1]}; - Bits<1> rs2_sign_bit = X[rs2][xlen()-1]; - Bits src2 = {{xlen(){rs2_sign_bit}}, X[rs2]}; + Bits<1> rs2_sign_bit = X[rs2][xlen()-1]; + Bits src2 = {{xlen(){rs2_sign_bit}}, X[rs2]}; - # grab the high half of the result, and put it in rd - X[rd] = (src1 * src2)[(xlen()*8'd2)-1:xlen()]; + # grab the high half of the result, and put it in rd + X[rd] = (src1 * src2)[(xlen()*8'd2)-1:xlen()]; - sail(): | - { - if extension("M") | haveZmmul() then { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let rs1_int : int = if signed1 then signed(rs1_val) else unsigned(rs1_val); - let rs2_int : int = if signed2 then signed(rs2_val) else unsigned(rs2_val); - let result_wide = to_bits(2 * sizeof(xlen), rs1_int * rs2_int); - let result = if high - then result_wide[(2 * sizeof(xlen) - 1) .. sizeof(xlen)] - else result_wide[(sizeof(xlen) - 1) .. 0]; - X(rd) = result; - RETIRE_SUCCESS - } else { - handle_illegal(); - RETIRE_FAIL - } +sail(): | + { + if extension("M") | haveZmmul() then { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let rs1_int : int = if signed1 then signed(rs1_val) else unsigned(rs1_val); + let rs2_int : int = if signed2 then signed(rs2_val) else unsigned(rs2_val); + let result_wide = to_bits(2 * sizeof(xlen), rs1_int * rs2_int); + let result = if high + then result_wide[(2 * sizeof(xlen) - 1) .. sizeof(xlen)] + else result_wide[(sizeof(xlen) - 1) .. 0]; + X(rd) = result; + RETIRE_SUCCESS + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/M/mulhsu.yaml b/arch/inst/M/mulhsu.yaml index 32ae229c9..ad58d2f7d 100644 --- a/arch/inst/M/mulhsu.yaml +++ b/arch/inst/M/mulhsu.yaml @@ -1,69 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -mulhsu: - long_name: Signed/unsigned multiply high - description: | - Multiply the signed value in rs1 by the unsigned value in rs2, and store the upper half of the result in rd. - The lower half is thrown away. +$schema: "inst_schema.json#" +kind: instruction +name: mulhsu +long_name: Signed/unsigned multiply high +description: | + Multiply the signed value in rs1 by the unsigned value in rs2, and store the upper half of the result in rd. + The lower half is thrown away. - If both the upper and lower halves are needed, it suggested to use the sequence: + If both the upper and lower halves are needed, it suggested to use the sequence: - --- - mulhsu rdh, rs1, rs2 - mul rdl, rs1, rs2 - --- + --- + mulhsu rdh, rs1, rs2 + mul rdl, rs1, rs2 + --- - Microarchitectures may look for that sequence and fuse the operations. - definedBy: - anyOf: [M, Zmmul] - assembly: xd, xs1, xs2 - encoding: - match: 0000001----------010-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + Microarchitectures may look for that sequence and fuse the operations. +definedBy: + anyOf: [M, Zmmul] +assembly: xd, xs1, xs2 +encoding: + match: 0000001----------010-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - # enlarge and extend the sources - Bits<1> rs1_sign_bit = X[rs1][XLEN-1]; - Bits src1 = {{XLEN{rs1_sign_bit}}, X[rs1]}; - Bits src2 = {{XLEN{1'b0}}, X[rs2]}; + # enlarge and extend the sources + Bits<1> rs1_sign_bit = X[rs1][XLEN-1]; + Bits src1 = {{XLEN{rs1_sign_bit}}, X[rs1]}; + Bits src2 = {{XLEN{1'b0}}, X[rs2]}; - X[rd] = (src1 * src2)[(XLEN*8'd2)-1:XLEN]; + X[rd] = (src1 * src2)[(XLEN*8'd2)-1:XLEN]; - sail(): | - { - if extension("M") | haveZmmul() then { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let rs1_int : int = if signed1 then signed(rs1_val) else unsigned(rs1_val); - let rs2_int : int = if signed2 then signed(rs2_val) else unsigned(rs2_val); - let result_wide = to_bits(2 * sizeof(xlen), rs1_int * rs2_int); - let result = if high - then result_wide[(2 * sizeof(xlen) - 1) .. sizeof(xlen)] - else result_wide[(sizeof(xlen) - 1) .. 0]; - X(rd) = result; - RETIRE_SUCCESS - } else { - handle_illegal(); - RETIRE_FAIL - } +sail(): | + { + if extension("M") | haveZmmul() then { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let rs1_int : int = if signed1 then signed(rs1_val) else unsigned(rs1_val); + let rs2_int : int = if signed2 then signed(rs2_val) else unsigned(rs2_val); + let result_wide = to_bits(2 * sizeof(xlen), rs1_int * rs2_int); + let result = if high + then result_wide[(2 * sizeof(xlen) - 1) .. sizeof(xlen)] + else result_wide[(sizeof(xlen) - 1) .. 0]; + X(rd) = result; + RETIRE_SUCCESS + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/M/mulhu.yaml b/arch/inst/M/mulhu.yaml index 006815018..af3838350 100644 --- a/arch/inst/M/mulhu.yaml +++ b/arch/inst/M/mulhu.yaml @@ -1,68 +1,70 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -mulhu: - long_name: Unsigned multiply high - description: | - Multiply the unsigned values in rs1 to rs2, and store the upper half of the result in rd. - The lower half is thrown away. +$schema: "inst_schema.json#" +kind: instruction +name: mulhu +long_name: Unsigned multiply high +description: | + Multiply the unsigned values in rs1 to rs2, and store the upper half of the result in rd. + The lower half is thrown away. - If both the upper and lower halves are needed, it suggested to use the sequence: + If both the upper and lower halves are needed, it suggested to use the sequence: - --- - mulhu rdh, rs1, rs2 - mul rdl, rs1, rs2 - --- + --- + mulhu rdh, rs1, rs2 + mul rdl, rs1, rs2 + --- - Microarchitectures may look for that sequence and fuse the operations. - definedBy: - anyOf: [M, Zmmul] - assembly: xd, xs1, xs2 - encoding: - match: 0000001----------011-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + Microarchitectures may look for that sequence and fuse the operations. +definedBy: + anyOf: [M, Zmmul] +assembly: xd, xs1, xs2 +encoding: + match: 0000001----------011-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - # enlarge and zero-extend the sources - Bits src1 = {{XLEN{1'b0}}, X[rs1]}; - Bits src2 = {{XLEN{1'b0}}, X[rs2]}; + # enlarge and zero-extend the sources + Bits src1 = {{XLEN{1'b0}}, X[rs1]}; + Bits src2 = {{XLEN{1'b0}}, X[rs2]}; - X[rd] = (src1 * src2)[(XLEN*8'd2)-1:XLEN]; + X[rd] = (src1 * src2)[(XLEN*8'd2)-1:XLEN]; - sail(): | - { - if extension("M") | haveZmmul() then { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let rs1_int : int = if signed1 then signed(rs1_val) else unsigned(rs1_val); - let rs2_int : int = if signed2 then signed(rs2_val) else unsigned(rs2_val); - let result_wide = to_bits(2 * sizeof(xlen), rs1_int * rs2_int); - let result = if high - then result_wide[(2 * sizeof(xlen) - 1) .. sizeof(xlen)] - else result_wide[(sizeof(xlen) - 1) .. 0]; - X(rd) = result; - RETIRE_SUCCESS - } else { - handle_illegal(); - RETIRE_FAIL - } +sail(): | + { + if extension("M") | haveZmmul() then { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let rs1_int : int = if signed1 then signed(rs1_val) else unsigned(rs1_val); + let rs2_int : int = if signed2 then signed(rs2_val) else unsigned(rs2_val); + let result_wide = to_bits(2 * sizeof(xlen), rs1_int * rs2_int); + let result = if high + then result_wide[(2 * sizeof(xlen) - 1) .. sizeof(xlen)] + else result_wide[(sizeof(xlen) - 1) .. 0]; + X(rd) = result; + RETIRE_SUCCESS + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/M/mulw.yaml b/arch/inst/M/mulw.yaml index 073079ef7..457ab0bac 100644 --- a/arch/inst/M/mulw.yaml +++ b/arch/inst/M/mulw.yaml @@ -1,70 +1,72 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -mulw: - long_name: Signed 32-bit multiply - description: | - Multiplies the lower 32 bits of the source registers, placing the sign-extension of the - lower 32 bits of the result into the destination register. +$schema: "inst_schema.json#" +kind: instruction +name: mulw +long_name: Signed 32-bit multiply +description: | + Multiplies the lower 32 bits of the source registers, placing the sign-extension of the + lower 32 bits of the result into the destination register. - Any overflow is thrown away. + Any overflow is thrown away. - [NOTE] - In RV64, MUL can be used to obtain the upper 32 bits of the 64-bit product, - but signed arguments must be proper 32-bit signed values, whereas unsigned arguments - must have their upper 32 bits clear. If the arguments are not known to be sign- or zero-extended, - an alternative is to shift both arguments left by 32 bits, then use MULH[[S]U]. - definedBy: - anyOf: [M, Zmmul] - assembly: xd, xs1, xs2 - encoding: - match: 0000001----------000-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + [NOTE] + In RV64, MUL can be used to obtain the upper 32 bits of the 64-bit product, + but signed arguments must be proper 32-bit signed values, whereas unsigned arguments + must have their upper 32 bits clear. If the arguments are not known to be sign- or zero-extended, + an alternative is to shift both arguments left by 32 bits, then use MULH[[S]U]. +definedBy: + anyOf: [M, Zmmul] +assembly: xd, xs1, xs2 +encoding: + match: 0000001----------000-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - Bits<32> src1 = X[rs1][31:0]; - Bits<32> src2 = X[rs2][31:0]; + Bits<32> src1 = X[rs1][31:0]; + Bits<32> src2 = X[rs2][31:0]; - Bits<32> result = src1 * src2; - Bits<1> sign_bit = result[31]; + Bits<32> result = src1 * src2; + Bits<1> sign_bit = result[31]; - # return the sign-extended result - X[rd] = {{32{sign_bit}}, result}; + # return the sign-extended result + X[rd] = {{32{sign_bit}}, result}; - sail(): | - { - if extension("M") | haveZmmul() then { - let rs1_val = X(rs1)[31..0]; - let rs2_val = X(rs2)[31..0]; - let rs1_int : int = signed(rs1_val); - let rs2_int : int = signed(rs2_val); - /* to_bits requires expansion to 64 bits followed by truncation */ - let result32 = to_bits(64, rs1_int * rs2_int)[31..0]; - let result : xlenbits = sign_extend(result32); - X(rd) = result; - RETIRE_SUCCESS - } else { - handle_illegal(); - RETIRE_FAIL - } +sail(): | + { + if extension("M") | haveZmmul() then { + let rs1_val = X(rs1)[31..0]; + let rs2_val = X(rs2)[31..0]; + let rs1_int : int = signed(rs1_val); + let rs2_int : int = signed(rs2_val); + /* to_bits requires expansion to 64 bits followed by truncation */ + let result32 = to_bits(64, rs1_int * rs2_int)[31..0]; + let result : xlenbits = sign_extend(result32); + X(rd) = result; + RETIRE_SUCCESS + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/M/rem.yaml b/arch/inst/M/rem.yaml index da87a828a..1f4dfd8c0 100644 --- a/arch/inst/M/rem.yaml +++ b/arch/inst/M/rem.yaml @@ -1,69 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -rem: - long_name: Signed remainder - description: | - Calculate the remainder of signed division of rs1 by rs2, and store the result in rd. +$schema: "inst_schema.json#" +kind: instruction +name: rem +long_name: Signed remainder +description: | + Calculate the remainder of signed division of rs1 by rs2, and store the result in rd. - If the value in register rs2 is zero, write the value in rs1 into rd; + If the value in register rs2 is zero, write the value in rs1 into rd; - If the result of the division overflows, write zero into rd; - definedBy: M - assembly: xd, xs1, xs2 - encoding: - match: 0000001----------110-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + If the result of the division overflows, write zero into rd; +definedBy: M +assembly: xd, xs1, xs2 +encoding: + match: 0000001----------110-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg src1 = X[rs1]; + XReg src2 = X[rs2]; + + if (src2 == 0) { + # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined + # to be the dividend + X[rd] = src1; + + } else if ((src1 == {1'b1, {XLEN-1{1'b0}}}) && (src2 == {XLEN{1'b1}})) { + # signed overflow. Since RISC-V does not have arithmetic exceptions, the result is defined + # to be zero + X[rd] = 0; - XReg src1 = X[rs1]; - XReg src2 = X[rs2]; + } else { + X[rd] = $signed(src1) % $signed(src2); + } - if (src2 == 0) { - # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined - # to be the dividend - X[rd] = src1; - - } else if ((src1 == {1'b1, {XLEN-1{1'b0}}}) && (src2 == {XLEN{1'b1}})) { - # signed overflow. Since RISC-V does not have arithmetic exceptions, the result is defined - # to be zero - X[rd] = 0; +sail(): | + { + if extension("M") then { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); + let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); + let r : int = if rs2_int == 0 then rs1_int else rem_round_zero(rs1_int, rs2_int); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + X(rd) = to_bits(sizeof(xlen), r); + RETIRE_SUCCESS } else { - X[rd] = $signed(src1) % $signed(src2); + handle_illegal(); + RETIRE_FAIL } + } - sail(): | - { - if extension("M") then { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); - let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); - let r : int = if rs2_int == 0 then rs1_int else rem_round_zero(rs1_int, rs2_int); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - X(rd) = to_bits(sizeof(xlen), r); - RETIRE_SUCCESS - } else { - handle_illegal(); - RETIRE_FAIL - } - } - - diff --git a/arch/inst/M/remu.yaml b/arch/inst/M/remu.yaml index 8c067ac62..e3ad1c457 100644 --- a/arch/inst/M/remu.yaml +++ b/arch/inst/M/remu.yaml @@ -1,59 +1,61 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -remu: - long_name: Unsigned remainder - description: | - Calculate the remainder of unsigned division of rs1 by rs2, and store the result in rd. - definedBy: M - assembly: xd, xs1, xs2 - encoding: - match: 0000001----------111-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: remu +long_name: Unsigned remainder +description: | + Calculate the remainder of unsigned division of rs1 by rs2, and store the result in rd. +definedBy: M +assembly: xd, xs1, xs2 +encoding: + match: 0000001----------111-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg src1 = X[rs1]; + XReg src2 = X[rs2]; - XReg src1 = X[rs1]; - XReg src2 = X[rs2]; + if (src2 == 0) { + # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined + # to be the dividend + X[rd] = src1; + } else { + X[rd] = src1 % src2; + } - if (src2 == 0) { - # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined - # to be the dividend - X[rd] = src1; + +sail(): | + { + if extension("M") then { + let rs1_val = X(rs1); + let rs2_val = X(rs2); + let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); + let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); + let r : int = if rs2_int == 0 then rs1_int else rem_round_zero(rs1_int, rs2_int); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + X(rd) = to_bits(sizeof(xlen), r); + RETIRE_SUCCESS } else { - X[rd] = src1 % src2; + handle_illegal(); + RETIRE_FAIL } + } - sail(): | - { - if extension("M") then { - let rs1_val = X(rs1); - let rs2_val = X(rs2); - let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); - let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); - let r : int = if rs2_int == 0 then rs1_int else rem_round_zero(rs1_int, rs2_int); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - X(rd) = to_bits(sizeof(xlen), r); - RETIRE_SUCCESS - } else { - handle_illegal(); - RETIRE_FAIL - } - } - - diff --git a/arch/inst/M/remuw.yaml b/arch/inst/M/remuw.yaml index 368e3be2b..64a52a1b8 100644 --- a/arch/inst/M/remuw.yaml +++ b/arch/inst/M/remuw.yaml @@ -1,71 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -remuw: - long_name: Unsigned 32-bit remainder - description: | - Calculate the remainder of unsigned division of the 32-bit values in rs1 by rs2, - and store the sign-extended result in rd. +$schema: "inst_schema.json#" +kind: instruction +name: remuw +long_name: Unsigned 32-bit remainder +description: | + Calculate the remainder of unsigned division of the 32-bit values in rs1 by rs2, + and store the sign-extended result in rd. - If the value in rs2 is zero, rd gets the sign-extended value in rs1. - definedBy: M - assembly: xd, xs1, xs2 - encoding: - match: 0000001----------111-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + If the value in rs2 is zero, rd gets the sign-extended value in rs1. +definedBy: M +assembly: xd, xs1, xs2 +encoding: + match: 0000001----------111-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - Bits<32> src1 = X[rs1][31:0]; - Bits<32> src2 = X[rs2][31:0]; + Bits<32> src1 = X[rs1][31:0]; + Bits<32> src2 = X[rs2][31:0]; - if (src2 == 0) { - # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined - # to be the dividend - Bits<1> sign_bit = src1[31]; - X[rd] = {{32{sign_bit}}, src1}; + if (src2 == 0) { + # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined + # to be the dividend + Bits<1> sign_bit = src1[31]; + X[rd] = {{32{sign_bit}}, src1}; - } else { - # no special case + } else { + # no special case - Bits<32> result = src1 % src2; + Bits<32> result = src1 % src2; - Bits<1> sign_bit = result[31]; + Bits<1> sign_bit = result[31]; - X[rd] = {{32{sign_bit}}, result}; - } + X[rd] = {{32{sign_bit}}, result}; + } - sail(): | - { - if extension("M") then { - let rs1_val = X(rs1)[31..0]; - let rs2_val = X(rs2)[31..0]; - let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); - let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); - let r : int = if rs2_int == 0 then rs1_int else rem_round_zero(rs1_int, rs2_int); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - X(rd) = sign_extend(to_bits(32, r)); - RETIRE_SUCCESS - } else { - handle_illegal(); - RETIRE_FAIL - } +sail(): | + { + if extension("M") then { + let rs1_val = X(rs1)[31..0]; + let rs2_val = X(rs2)[31..0]; + let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); + let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); + let r : int = if rs2_int == 0 then rs1_int else rem_round_zero(rs1_int, rs2_int); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + X(rd) = sign_extend(to_bits(32, r)); + RETIRE_SUCCESS + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/M/remw.yaml b/arch/inst/M/remw.yaml index 293d8f167..9df788d0b 100644 --- a/arch/inst/M/remw.yaml +++ b/arch/inst/M/remw.yaml @@ -1,75 +1,77 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -remw: - long_name: Signed 32-bit remainder - description: | - Calculate the remainder of signed division of the 32-bit values rs1 by rs2, - and store the sign-extended result in rd. +$schema: "inst_schema.json#" +kind: instruction +name: remw +long_name: Signed 32-bit remainder +description: | + Calculate the remainder of signed division of the 32-bit values rs1 by rs2, + and store the sign-extended result in rd. - If the value in register rs2 is zero, write the sign-extended 32-bit value in rs1 into rd; + If the value in register rs2 is zero, write the sign-extended 32-bit value in rs1 into rd; - If the result of the division overflows, write zero into rd; - definedBy: M - assembly: xd, xs1, xs2 - encoding: - match: 0000001----------110-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + If the result of the division overflows, write zero into rd; +definedBy: M +assembly: xd, xs1, xs2 +encoding: + match: 0000001----------110-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - Bits<32> src1 = X[rs1][31:0]; - Bits<32> src2 = X[rs2][31:0]; + Bits<32> src1 = X[rs1][31:0]; + Bits<32> src2 = X[rs2][31:0]; - if (src2 == 0) { - # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined - # to be the dividend, sign extended to into the 64-bit register - Bits<1> sign_bit = src1[31]; - X[rd] = {{32{sign_bit}}, src1}; - - } else if ((src1 == {33'b1, 31'b0}) && (src2 == 32'b1)) { - # signed overflow. Since RISC-V does not have arithmetic exceptions, the result is defined - # to be zero - X[rd] = 0; + if (src2 == 0) { + # division by zero. Since RISC-V does not have arithmetic exceptions, the result is defined + # to be the dividend, sign extended to into the 64-bit register + Bits<1> sign_bit = src1[31]; + X[rd] = {{32{sign_bit}}, src1}; + + } else if ((src1 == {33'b1, 31'b0}) && (src2 == 32'b1)) { + # signed overflow. Since RISC-V does not have arithmetic exceptions, the result is defined + # to be zero + X[rd] = 0; - } else { - # no special case - Bits<32> result = $signed(src1) % $signed(src2); - Bits<1> sign_bit = result[31]; + } else { + # no special case + Bits<32> result = $signed(src1) % $signed(src2); + Bits<1> sign_bit = result[31]; - X[rd] = {{32{sign_bit}}, result}; - } + X[rd] = {{32{sign_bit}}, result}; + } - sail(): | - { - if extension("M") then { - let rs1_val = X(rs1)[31..0]; - let rs2_val = X(rs2)[31..0]; - let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); - let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); - let r : int = if rs2_int == 0 then rs1_int else rem_round_zero(rs1_int, rs2_int); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - X(rd) = sign_extend(to_bits(32, r)); - RETIRE_SUCCESS - } else { - handle_illegal(); - RETIRE_FAIL - } +sail(): | + { + if extension("M") then { + let rs1_val = X(rs1)[31..0]; + let rs2_val = X(rs2)[31..0]; + let rs1_int : int = if s then signed(rs1_val) else unsigned(rs1_val); + let rs2_int : int = if s then signed(rs2_val) else unsigned(rs2_val); + let r : int = if rs2_int == 0 then rs1_int else rem_round_zero(rs1_int, rs2_int); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + X(rd) = sign_extend(to_bits(32, r)); + RETIRE_SUCCESS + } else { + handle_illegal(); + RETIRE_FAIL } - - + } + + diff --git a/arch/inst/Q/fadd.q.yaml b/arch/inst/Q/fadd.q.yaml index f1d441812..7eaf4023f 100644 --- a/arch/inst/Q/fadd.q.yaml +++ b/arch/inst/Q/fadd.q.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fadd.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, qs1, qs2, rm - encoding: - match: 0000011------------------1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fadd.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, qs1, qs2, rm +encoding: + match: 0000011------------------1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fclass.q.yaml b/arch/inst/Q/fclass.q.yaml index 675c8af52..528c2b469 100644 --- a/arch/inst/Q/fclass.q.yaml +++ b/arch/inst/Q/fclass.q.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fclass.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: xd, qs1 - encoding: - match: 111001100000-----001-----1010011 - variables: - - name: qs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fclass.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: xd, qs1 +encoding: + match: 111001100000-----001-----1010011 + variables: + - name: qs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.d.q.yaml b/arch/inst/Q/fcvt.d.q.yaml index da4257106..4aaa5d951 100644 --- a/arch/inst/Q/fcvt.d.q.yaml +++ b/arch/inst/Q/fcvt.d.q.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.d.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: xd, qs1, rm - encoding: - match: 010000100011-------------1010011 - variables: - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.d.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: xd, qs1, rm +encoding: + match: 010000100011-------------1010011 + variables: + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.h.q.yaml b/arch/inst/Q/fcvt.h.q.yaml index 62dc6ae98..b0f9aaf6c 100644 --- a/arch/inst/Q/fcvt.h.q.yaml +++ b/arch/inst/Q/fcvt.h.q.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.h.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Q, Zfh] - assembly: xd, qs1, rm - encoding: - match: 010001000011-------------1010011 - variables: - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.h.q +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Q, Zfh] +assembly: xd, qs1, rm +encoding: + match: 010001000011-------------1010011 + variables: + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.l.q.yaml b/arch/inst/Q/fcvt.l.q.yaml index 8c7aae209..c6a76dbac 100644 --- a/arch/inst/Q/fcvt.l.q.yaml +++ b/arch/inst/Q/fcvt.l.q.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.l.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - base: 64 - assembly: xd, qs1, rm - encoding: - match: 110001100010-------------1010011 - variables: - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.l.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +base: 64 +assembly: xd, qs1, rm +encoding: + match: 110001100010-------------1010011 + variables: + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.lu.q.yaml b/arch/inst/Q/fcvt.lu.q.yaml index 9538853f5..0ee3cf010 100644 --- a/arch/inst/Q/fcvt.lu.q.yaml +++ b/arch/inst/Q/fcvt.lu.q.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.lu.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - base: 64 - assembly: qd, hs1, rm - encoding: - match: 110001100011-------------1010011 - variables: - - name: hs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.lu.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +base: 64 +assembly: qd, hs1, rm +encoding: + match: 110001100011-------------1010011 + variables: + - name: hs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.q.d.yaml b/arch/inst/Q/fcvt.q.d.yaml index cfd521f1a..a8c00bcd0 100644 --- a/arch/inst/Q/fcvt.q.d.yaml +++ b/arch/inst/Q/fcvt.q.d.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.q.d: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: dd, fs1, rm - encoding: - match: 010001100001-------------1010011 - variables: - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: dd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.q.d +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: dd, fs1, rm +encoding: + match: 010001100001-------------1010011 + variables: + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: dd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.q.h.yaml b/arch/inst/Q/fcvt.q.h.yaml index 6f553b585..e315ca75c 100644 --- a/arch/inst/Q/fcvt.q.h.yaml +++ b/arch/inst/Q/fcvt.q.h.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.q.h: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Q, Zfh] - assembly: hd, qs1, rm - encoding: - match: 010001100010-------------1010011 - variables: - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: hd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.q.h +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Q, Zfh] +assembly: hd, qs1, rm +encoding: + match: 010001100010-------------1010011 + variables: + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: hd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.q.l.yaml b/arch/inst/Q/fcvt.q.l.yaml index 7d162c894..eff9c9342 100644 --- a/arch/inst/Q/fcvt.q.l.yaml +++ b/arch/inst/Q/fcvt.q.l.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.q.l: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - base: 64 - assembly: qd, xs1, rm - encoding: - match: 110101100010-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.q.l +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +base: 64 +assembly: qd, xs1, rm +encoding: + match: 110101100010-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.q.lu.yaml b/arch/inst/Q/fcvt.q.lu.yaml index 3e072c041..fcc7555a2 100644 --- a/arch/inst/Q/fcvt.q.lu.yaml +++ b/arch/inst/Q/fcvt.q.lu.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.q.lu: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - base: 64 - assembly: qd, xs1, rm - encoding: - match: 110101100011-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.q.lu +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +base: 64 +assembly: qd, xs1, rm +encoding: + match: 110101100011-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.q.s.yaml b/arch/inst/Q/fcvt.q.s.yaml index 9e3eef314..f01c73066 100644 --- a/arch/inst/Q/fcvt.q.s.yaml +++ b/arch/inst/Q/fcvt.q.s.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.q.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, fs1, rm - encoding: - match: 010001100000-------------1010011 - variables: - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.q.s +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, fs1, rm +encoding: + match: 010001100000-------------1010011 + variables: + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.q.w.yaml b/arch/inst/Q/fcvt.q.w.yaml index fd1406fab..e03a6f7af 100644 --- a/arch/inst/Q/fcvt.q.w.yaml +++ b/arch/inst/Q/fcvt.q.w.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.q.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: fd, xs1, rm - encoding: - match: 110101100000-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.q.w +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: fd, xs1, rm +encoding: + match: 110101100000-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.q.wu.yaml b/arch/inst/Q/fcvt.q.wu.yaml index 88fbba374..2dd85ff07 100644 --- a/arch/inst/Q/fcvt.q.wu.yaml +++ b/arch/inst/Q/fcvt.q.wu.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.q.wu: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, xs1, rm - encoding: - match: 110101100001-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.q.wu +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, xs1, rm +encoding: + match: 110101100001-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.s.q.yaml b/arch/inst/Q/fcvt.s.q.yaml index e4bba25c2..bb24b7ec7 100644 --- a/arch/inst/Q/fcvt.s.q.yaml +++ b/arch/inst/Q/fcvt.s.q.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.s.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: fd, qs1, rm - encoding: - match: 010000000011-------------1010011 - variables: - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.s.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: fd, qs1, rm +encoding: + match: 010000000011-------------1010011 + variables: + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.w.q.yaml b/arch/inst/Q/fcvt.w.q.yaml index 112e366d1..c414a695a 100644 --- a/arch/inst/Q/fcvt.w.q.yaml +++ b/arch/inst/Q/fcvt.w.q.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.w.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: xd, qs1, rm - encoding: - match: 110001100000-------------1010011 - variables: - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.w.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: xd, qs1, rm +encoding: + match: 110001100000-------------1010011 + variables: + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fcvt.wu.q.yaml b/arch/inst/Q/fcvt.wu.q.yaml index a71c9f176..54b157cdd 100644 --- a/arch/inst/Q/fcvt.wu.q.yaml +++ b/arch/inst/Q/fcvt.wu.q.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.wu.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: xd, xs1, rm - encoding: - match: 110001100001-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.wu.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: xd, xs1, rm +encoding: + match: 110001100001-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fdiv.q.yaml b/arch/inst/Q/fdiv.q.yaml index 0274c45bd..56f1cd7c5 100644 --- a/arch/inst/Q/fdiv.q.yaml +++ b/arch/inst/Q/fdiv.q.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fdiv.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, qs1, qs2, rm - encoding: - match: 0001111------------------1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fdiv.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, qs1, qs2, rm +encoding: + match: 0001111------------------1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/feq.q.yaml b/arch/inst/Q/feq.q.yaml index a81675101..8522aaa50 100644 --- a/arch/inst/Q/feq.q.yaml +++ b/arch/inst/Q/feq.q.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -feq.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: xd, qs1, qs2 - encoding: - match: 1010011----------010-----1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: feq.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: xd, qs1, qs2 +encoding: + match: 1010011----------010-----1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fle.q.yaml b/arch/inst/Q/fle.q.yaml index a7c49ad49..e684af70a 100644 --- a/arch/inst/Q/fle.q.yaml +++ b/arch/inst/Q/fle.q.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fle.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: xd, qs1, qs2 - encoding: - match: 1010011----------000-----1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fle.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: xd, qs1, qs2 +encoding: + match: 1010011----------000-----1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fleq.q.yaml b/arch/inst/Q/fleq.q.yaml index 32dc2e02b..155862a4c 100644 --- a/arch/inst/Q/fleq.q.yaml +++ b/arch/inst/Q/fleq.q.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fleq.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Q, Zfa] - assembly: xd, qs1, qs2 - encoding: - match: 1010011----------100-----1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fleq.q +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Q, Zfa] +assembly: xd, qs1, qs2 +encoding: + match: 1010011----------100-----1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fli.q.yaml b/arch/inst/Q/fli.q.yaml index f80db1ef2..87b4eb709 100644 --- a/arch/inst/Q/fli.q.yaml +++ b/arch/inst/Q/fli.q.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fli.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Q, Zfa] - assembly: fd, qs1 - encoding: - match: 111101100001-----000-----1010011 - variables: - - name: qs1 - location: 19-15 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fli.q +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Q, Zfa] +assembly: fd, qs1 +encoding: + match: 111101100001-----000-----1010011 + variables: + - name: qs1 + location: 19-15 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/flq.yaml b/arch/inst/Q/flq.yaml index 440da71d7..4ca374e8d 100644 --- a/arch/inst/Q/flq.yaml +++ b/arch/inst/Q/flq.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -flq: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, xs1, imm - encoding: - match: -----------------100-----0000111 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: flq +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, xs1, imm +encoding: + match: -----------------100-----0000111 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/flt.q.yaml b/arch/inst/Q/flt.q.yaml index 0625facf8..404b81da4 100644 --- a/arch/inst/Q/flt.q.yaml +++ b/arch/inst/Q/flt.q.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -flt.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: xd, qs1, qs2 - encoding: - match: 1010011----------001-----1010011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: flt.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: xd, qs1, qs2 +encoding: + match: 1010011----------001-----1010011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fltq.q.yaml b/arch/inst/Q/fltq.q.yaml index 38116d07d..04ba644fb 100644 --- a/arch/inst/Q/fltq.q.yaml +++ b/arch/inst/Q/fltq.q.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fltq.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Q, Zfa] - assembly: qd, qs1, qs2 - encoding: - match: 1010011----------101-----1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fltq.q +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Q, Zfa] +assembly: qd, qs1, qs2 +encoding: + match: 1010011----------101-----1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fmadd.q.yaml b/arch/inst/Q/fmadd.q.yaml index ce1923233..43f288a43 100644 --- a/arch/inst/Q/fmadd.q.yaml +++ b/arch/inst/Q/fmadd.q.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmadd.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, qs1, qs2, qs3, rm - encoding: - match: -----11------------------1000011 - variables: - - name: qs3 - location: 31-27 - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fmadd.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, qs1, qs2, qs3, rm +encoding: + match: -----11------------------1000011 + variables: + - name: qs3 + location: 31-27 + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fmax.q.yaml b/arch/inst/Q/fmax.q.yaml index 729b02e5e..5847f13ec 100644 --- a/arch/inst/Q/fmax.q.yaml +++ b/arch/inst/Q/fmax.q.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmax.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, qs1, qs2 - encoding: - match: 0010111----------001-----1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fmax.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, qs1, qs2 +encoding: + match: 0010111----------001-----1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fmaxm.q.yaml b/arch/inst/Q/fmaxm.q.yaml index a26aac3d1..8805cbb63 100644 --- a/arch/inst/Q/fmaxm.q.yaml +++ b/arch/inst/Q/fmaxm.q.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmaxm.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Q, Zfa] - assembly: qd, qs1, qs2 - encoding: - match: 0010111----------011-----1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fmaxm.q +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Q, Zfa] +assembly: qd, qs1, qs2 +encoding: + match: 0010111----------011-----1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fmin.q.yaml b/arch/inst/Q/fmin.q.yaml index ff702b8ee..c46d946df 100644 --- a/arch/inst/Q/fmin.q.yaml +++ b/arch/inst/Q/fmin.q.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmin.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: xd, xs1, xs2 - encoding: - match: 0010111----------000-----1010011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fmin.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: xd, xs1, xs2 +encoding: + match: 0010111----------000-----1010011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fminm.q.yaml b/arch/inst/Q/fminm.q.yaml index c25379036..853f02fb6 100644 --- a/arch/inst/Q/fminm.q.yaml +++ b/arch/inst/Q/fminm.q.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fminm.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Q, Zfa] - assembly: qd, qs1, qs2 - encoding: - match: 0010111----------010-----1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fminm.q +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Q, Zfa] +assembly: qd, qs1, qs2 +encoding: + match: 0010111----------010-----1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fmsub.q.yaml b/arch/inst/Q/fmsub.q.yaml index 93e3df4d4..f036761a9 100644 --- a/arch/inst/Q/fmsub.q.yaml +++ b/arch/inst/Q/fmsub.q.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmsub.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, qs1, qs2, qs3, rm - encoding: - match: -----11------------------1000111 - variables: - - name: qs3 - location: 31-27 - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fmsub.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, qs1, qs2, qs3, rm +encoding: + match: -----11------------------1000111 + variables: + - name: qs3 + location: 31-27 + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fmul.q.yaml b/arch/inst/Q/fmul.q.yaml index 8d411d016..be9d0d85d 100644 --- a/arch/inst/Q/fmul.q.yaml +++ b/arch/inst/Q/fmul.q.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmul.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, qs1, qs2, rm - encoding: - match: 0001011------------------1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fmul.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, qs1, qs2, rm +encoding: + match: 0001011------------------1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fmvh.x.q.yaml b/arch/inst/Q/fmvh.x.q.yaml index b85a62c85..73fbe8c67 100644 --- a/arch/inst/Q/fmvh.x.q.yaml +++ b/arch/inst/Q/fmvh.x.q.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmvh.x.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Q, Zfa] - base: 64 - assembly: xd, qs1 - encoding: - match: 111001100001-----000-----1010011 - variables: - - name: qs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fmvh.x.q +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Q, Zfa] +base: 64 +assembly: xd, qs1 +encoding: + match: 111001100001-----000-----1010011 + variables: + - name: qs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fmvp.q.x.yaml b/arch/inst/Q/fmvp.q.x.yaml index ae04f9234..2f450b0f6 100644 --- a/arch/inst/Q/fmvp.q.x.yaml +++ b/arch/inst/Q/fmvp.q.x.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmvp.q.x: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Q, Zfa] - base: 64 - assembly: qd, xs1, xs2 - encoding: - match: 1011011----------000-----1010011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fmvp.q.x +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Q, Zfa] +base: 64 +assembly: qd, xs1, xs2 +encoding: + match: 1011011----------000-----1010011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fnmadd.q.yaml b/arch/inst/Q/fnmadd.q.yaml index 12bf29713..714401052 100644 --- a/arch/inst/Q/fnmadd.q.yaml +++ b/arch/inst/Q/fnmadd.q.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fnmadd.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, qs1, qs2, qs3, rm - encoding: - match: -----11------------------1001111 - variables: - - name: qs3 - location: 31-27 - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fnmadd.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, qs1, qs2, qs3, rm +encoding: + match: -----11------------------1001111 + variables: + - name: qs3 + location: 31-27 + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fnmsub.q.yaml b/arch/inst/Q/fnmsub.q.yaml index a20baabbf..a5d3ea469 100644 --- a/arch/inst/Q/fnmsub.q.yaml +++ b/arch/inst/Q/fnmsub.q.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fnmsub.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, qs1, qs2, qs3, rm - encoding: - match: -----11------------------1001011 - variables: - - name: qs3 - location: 31-27 - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fnmsub.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, qs1, qs2, qs3, rm +encoding: + match: -----11------------------1001011 + variables: + - name: qs3 + location: 31-27 + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fround.q.yaml b/arch/inst/Q/fround.q.yaml index 109750faf..664a7afe8 100644 --- a/arch/inst/Q/fround.q.yaml +++ b/arch/inst/Q/fround.q.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fround.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Q, Zfa] - assembly: qd, qs1, rm - encoding: - match: 010001100100-------------1010011 - variables: - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fround.q +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Q, Zfa] +assembly: qd, qs1, rm +encoding: + match: 010001100100-------------1010011 + variables: + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/froundnx.q.yaml b/arch/inst/Q/froundnx.q.yaml index 16750e019..e1a7effcb 100644 --- a/arch/inst/Q/froundnx.q.yaml +++ b/arch/inst/Q/froundnx.q.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -froundnx.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Q, Zfa] - assembly: qd, qs1, rm - encoding: - match: 010001100101-------------1010011 - variables: - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: froundnx.q +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Q, Zfa] +assembly: qd, qs1, rm +encoding: + match: 010001100101-------------1010011 + variables: + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fsgnj.q.yaml b/arch/inst/Q/fsgnj.q.yaml index 10940c34b..0406484c2 100644 --- a/arch/inst/Q/fsgnj.q.yaml +++ b/arch/inst/Q/fsgnj.q.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fsgnj.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, qs1, qs2 - encoding: - match: 0010011----------000-----1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - pseudoinstructions: - - when: (rs2 == rs1) - to: fmv.q - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fsgnj.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, qs1, qs2 +encoding: + match: 0010011----------000-----1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +pseudoinstructions: +- when: (rs2 == rs1) + to: fmv.q +operation(): | + diff --git a/arch/inst/Q/fsgnjn.q.yaml b/arch/inst/Q/fsgnjn.q.yaml index 4f0c2bc81..732314c79 100644 --- a/arch/inst/Q/fsgnjn.q.yaml +++ b/arch/inst/Q/fsgnjn.q.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fsgnjn.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, qs1, qs2 - encoding: - match: 0010011----------001-----1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - pseudoinstructions: - - when: (rs2 == rs1) - to: fneg.q - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fsgnjn.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, qs1, qs2 +encoding: + match: 0010011----------001-----1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +pseudoinstructions: +- when: (rs2 == rs1) + to: fneg.q +operation(): | + diff --git a/arch/inst/Q/fsgnjx.q.yaml b/arch/inst/Q/fsgnjx.q.yaml index fd03f0afd..82c27a27e 100644 --- a/arch/inst/Q/fsgnjx.q.yaml +++ b/arch/inst/Q/fsgnjx.q.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fsgnjx.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, qs1, qs2 - encoding: - match: 0010011----------010-----1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - pseudoinstructions: - - when: (rs2 == rs1) - to: fabs.q - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fsgnjx.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, qs1, qs2 +encoding: + match: 0010011----------010-----1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +pseudoinstructions: +- when: (rs2 == rs1) + to: fabs.q +operation(): | + diff --git a/arch/inst/Q/fsq.yaml b/arch/inst/Q/fsq.yaml index 8d897e055..564999cb9 100644 --- a/arch/inst/Q/fsq.yaml +++ b/arch/inst/Q/fsq.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fsq: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: xs1, qs2, imm - encoding: - match: -----------------100-----0100111 - variables: - - name: imm - location: 31-25|11-7 - - name: qs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fsq +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: xs1, qs2, imm +encoding: + match: -----------------100-----0100111 + variables: + - name: imm + location: 31-25|11-7 + - name: qs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fsqrt.q.yaml b/arch/inst/Q/fsqrt.q.yaml index 9d2db536f..73c157676 100644 --- a/arch/inst/Q/fsqrt.q.yaml +++ b/arch/inst/Q/fsqrt.q.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fsqrt.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, qs1, rm - encoding: - match: 010111100000-------------1010011 - variables: - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fsqrt.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, qs1, rm +encoding: + match: 010111100000-------------1010011 + variables: + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Q/fsub.q.yaml b/arch/inst/Q/fsub.q.yaml index d7ce985e5..7695cd763 100644 --- a/arch/inst/Q/fsub.q.yaml +++ b/arch/inst/Q/fsub.q.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fsub.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Q - assembly: qd, qs1, qs2, rm - encoding: - match: 0000111------------------1010011 - variables: - - name: qs2 - location: 24-20 - - name: qs1 - location: 19-15 - - name: rm - location: 14-12 - - name: qd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fsub.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Q +assembly: qd, qs1, qs2, rm +encoding: + match: 0000111------------------1010011 + variables: + - name: qs2 + location: 24-20 + - name: qs1 + location: 19-15 + - name: rm + location: 14-12 + - name: qd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/S/sfence.vma.yaml b/arch/inst/S/sfence.vma.yaml index d771cc740..e7e380ddd 100644 --- a/arch/inst/S/sfence.vma.yaml +++ b/arch/inst/S/sfence.vma.yaml @@ -1,325 +1,327 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sfence.vma: - long_name: Supervisor memory-management fence - definedBy: S - description: | - The supervisor memory-management fence instruction `SFENCE.VMA` is used to - synchronize updates to in-memory memory-management data structures with - current execution. Instruction execution causes implicit reads and - writes to these data structures; however, these implicit references are - ordinarily not ordered with respect to explicit loads and stores. - Executing an SFENCE.VMA instruction guarantees that any previous stores - already visible to the current RISC-V hart are ordered before certain - implicit references by subsequent instructions in that hart to the - memory-management data structures. The specific set of operations - ordered by SFENCE.VMA is determined by _rs1_ and _rs2_, as described - below. SFENCE.VMA is also used to invalidate entries in the - address-translation cache associated with a hart (see <>). Further details on the behavior of this instruction are described in <> and <>. - - [NOTE] - ==== - The SFENCE.VMA is used to flush any local hardware caches related to - address translation. It is specified as a fence rather than a TLB flush - to provide cleaner semantics with respect to which instructions are - affected by the flush operation and to support a wider variety of - dynamic caching structures and memory-management schemes. SFENCE.VMA is - also used by higher privilege levels to synchronize page table writes - and the address translation hardware. - ==== - - SFENCE.VMA orders only the local hart's implicit references to the - memory-management data structures. - - [NOTE] - ==== - Consequently, other harts must be notified separately when the - memory-management data structures have been modified. One approach is to - use 1) a local data fence to ensure local writes are visible globally, - then 2) an interprocessor interrupt to the other thread, then 3) a local - SFENCE.VMA in the interrupt handler of the remote thread, and finally 4) - signal back to originating thread that operation is complete. This is, - of course, the RISC-V analog to a TLB shootdown. - ==== - - For the common case that the translation data structures have only been - modified for a single address mapping (i.e., one page or superpage), - _rs1_ can specify a virtual address within that mapping to effect a - translation fence for that mapping only. Furthermore, for the common - case that the translation data structures have only been modified for a - single address-space identifier, _rs2_ can specify the address space. - The behavior of SFENCE.VMA depends on _rs1_ and _rs2_ as follows: - - * If __rs1__=`x0` and __rs2__=`x0`, the fence orders all reads and writes - made to any level of the page tables, for all address spaces. The fence - also invalidates all address-translation cache entries, for all address - spaces. - * If __rs1__=`x0` and __rs2__≠``x0``, the fence orders all - reads and writes made to any level of the page tables, but only for the - address space identified by integer register _rs2_. Accesses to _global_ - mappings (see <>) are not ordered. The - fence also invalidates all address-translation cache entries matching - the address space identified by integer register _rs2_, except for - entries containing global mappings. - * If __rs1__≠``x0`` and __rs2__=`x0`, the fence orders only - reads and writes made to leaf page table entries corresponding to the - virtual address in __rs1__, for all address spaces. The fence also - invalidates all address-translation cache entries that contain leaf page - table entries corresponding to the virtual address in _rs1_, for all - address spaces. - * If __rs1__≠``x0`` and __rs2__≠``x0``, the - fence orders only reads and writes made to leaf page table entries - corresponding to the virtual address in _rs1_, for the address space - identified by integer register _rs2_. Accesses to global mappings are - not ordered. The fence also invalidates all address-translation cache - entries that contain leaf page table entries corresponding to the - virtual address in _rs1_ and that match the address space identified by - integer register _rs2_, except for entries containing global mappings. - - If the value held in _rs1_ is not a valid virtual address, then the - SFENCE.VMA instruction has no effect. No exception is raised in this - case. - - When __rs2__≠``x0``, bits SXLEN-1:ASIDMAX of the value held - in _rs2_ are reserved for future standard use. Until their use is - defined by a standard extension, they should be zeroed by software and - ignored by current implementations. Furthermore, if - ASIDLEN asid = X[rs2][ASID_WIDTH-1:0]; - - if (mode() == PrivilegeMode::U) { +$schema: "inst_schema.json#" +kind: instruction +name: sfence.vma +long_name: Supervisor memory-management fence +definedBy: S +description: | + The supervisor memory-management fence instruction `SFENCE.VMA` is used to + synchronize updates to in-memory memory-management data structures with + current execution. Instruction execution causes implicit reads and + writes to these data structures; however, these implicit references are + ordinarily not ordered with respect to explicit loads and stores. + Executing an SFENCE.VMA instruction guarantees that any previous stores + already visible to the current RISC-V hart are ordered before certain + implicit references by subsequent instructions in that hart to the + memory-management data structures. The specific set of operations + ordered by SFENCE.VMA is determined by _rs1_ and _rs2_, as described + below. SFENCE.VMA is also used to invalidate entries in the + address-translation cache associated with a hart (see <>). Further details on the behavior of this instruction are described in <> and <>. + + [NOTE] + ==== + The SFENCE.VMA is used to flush any local hardware caches related to + address translation. It is specified as a fence rather than a TLB flush + to provide cleaner semantics with respect to which instructions are + affected by the flush operation and to support a wider variety of + dynamic caching structures and memory-management schemes. SFENCE.VMA is + also used by higher privilege levels to synchronize page table writes + and the address translation hardware. + ==== + + SFENCE.VMA orders only the local hart's implicit references to the + memory-management data structures. + + [NOTE] + ==== + Consequently, other harts must be notified separately when the + memory-management data structures have been modified. One approach is to + use 1) a local data fence to ensure local writes are visible globally, + then 2) an interprocessor interrupt to the other thread, then 3) a local + SFENCE.VMA in the interrupt handler of the remote thread, and finally 4) + signal back to originating thread that operation is complete. This is, + of course, the RISC-V analog to a TLB shootdown. + ==== + + For the common case that the translation data structures have only been + modified for a single address mapping (i.e., one page or superpage), + _rs1_ can specify a virtual address within that mapping to effect a + translation fence for that mapping only. Furthermore, for the common + case that the translation data structures have only been modified for a + single address-space identifier, _rs2_ can specify the address space. + The behavior of SFENCE.VMA depends on _rs1_ and _rs2_ as follows: + + * If __rs1__=`x0` and __rs2__=`x0`, the fence orders all reads and writes + made to any level of the page tables, for all address spaces. The fence + also invalidates all address-translation cache entries, for all address + spaces. + * If __rs1__=`x0` and __rs2__≠``x0``, the fence orders all + reads and writes made to any level of the page tables, but only for the + address space identified by integer register _rs2_. Accesses to _global_ + mappings (see <>) are not ordered. The + fence also invalidates all address-translation cache entries matching + the address space identified by integer register _rs2_, except for + entries containing global mappings. + * If __rs1__≠``x0`` and __rs2__=`x0`, the fence orders only + reads and writes made to leaf page table entries corresponding to the + virtual address in __rs1__, for all address spaces. The fence also + invalidates all address-translation cache entries that contain leaf page + table entries corresponding to the virtual address in _rs1_, for all + address spaces. + * If __rs1__≠``x0`` and __rs2__≠``x0``, the + fence orders only reads and writes made to leaf page table entries + corresponding to the virtual address in _rs1_, for the address space + identified by integer register _rs2_. Accesses to global mappings are + not ordered. The fence also invalidates all address-translation cache + entries that contain leaf page table entries corresponding to the + virtual address in _rs1_ and that match the address space identified by + integer register _rs2_, except for entries containing global mappings. + + If the value held in _rs1_ is not a valid virtual address, then the + SFENCE.VMA instruction has no effect. No exception is raised in this + case. + + When __rs2__≠``x0``, bits SXLEN-1:ASIDMAX of the value held + in _rs2_ are reserved for future standard use. Until their use is + defined by a standard extension, they should be zeroed by software and + ignored by current implementations. Furthermore, if + ASIDLEN asid = X[rs2][ASID_WIDTH-1:0]; + + if (mode() == PrivilegeMode::U) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + if (CSR[misa].H == 1 && mode() == PrivilegeMode::VU) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + if (CSR[mstatus].TVM == 1 && + ((mode() == PrivilegeMode::S) || (mode() == PrivilegeMode::VS))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + if (CSR[misa].H == 1 && CSR[hstatus].VTVM == 1 && mode() == PrivilegeMode::VS) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); + } + + if (!implemented?(ExtensionName::Sv32) && !implemented?(ExtensionName::Sv39) && !implemented?(ExtensionName::Sv48) && !implemented?(ExtensionName::Sv57)) { + if (TRAP_ON_SFENCE_VMA_WHEN_SATP_MODE_IS_READ_ONLY) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } - - if (CSR[misa].H == 1 && mode() == PrivilegeMode::VU) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - if (CSR[mstatus].TVM == 1 && - ((mode() == PrivilegeMode::S) || (mode() == PrivilegeMode::VS))) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - if (CSR[misa].H == 1 && CSR[hstatus].VTVM == 1 && mode() == PrivilegeMode::VS) { - raise (ExceptionCode::VirtualInstruction, mode(), $encoding); - } - - if (!implemented?(ExtensionName::Sv32) && !implemented?(ExtensionName::Sv39) && !implemented?(ExtensionName::Sv48) && !implemented?(ExtensionName::Sv57)) { - if (TRAP_ON_SFENCE_VMA_WHEN_SATP_MODE_IS_READ_ONLY) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } - - # note: this will default to "all", without globals included - VmaOrderType vma_type; - if (CSR[misa].H == 1 && mode() == PrivilegeMode::VS) { - vma_type.vsmode = true; - vma_type.single_vmid = true; - vma_type.vmid = CSR[hgatp].VMID; - } else { - vma_type.smode = true; - } - - if ((rs1 == 0) && (rs2 == 0)) { - # invalidate all translations, from all addresses and all ASIDs - # includes global mappings - vma_type.global = true; + } + + # note: this will default to "all", without globals included + VmaOrderType vma_type; + if (CSR[misa].H == 1 && mode() == PrivilegeMode::VS) { + vma_type.vsmode = true; + vma_type.single_vmid = true; + vma_type.vmid = CSR[hgatp].VMID; + } else { + vma_type.smode = true; + } + + if ((rs1 == 0) && (rs2 == 0)) { + # invalidate all translations, from all addresses and all ASIDs + # includes global mappings + vma_type.global = true; + + order_pgtbl_writes_before_vmafence(vma_type); + invalidate_translations(vma_type); + order_pgtbl_reads_after_vmafence(vma_type); + + } else if ((rs1 == 0) && (rs2 != 0)) { + # invalidates all translations from ASID 'asid' + # does not affect global mappings + vma_type.single_asid = true; + vma_type.asid = asid; + + order_pgtbl_writes_before_vmafence(vma_type); + invalidate_translations(vma_type); + order_pgtbl_reads_after_vmafence(vma_type); + + } else if ((rs1 != 0) && (rs2 == 0)) { + # invalidate all translations from leaf page tables containing 'vaddr' + # does not affect global mappings + if (canonical_vaddr?(vaddr)) { + vma_type.single_vaddr = true; + vma_type.vaddr = vaddr; order_pgtbl_writes_before_vmafence(vma_type); invalidate_translations(vma_type); order_pgtbl_reads_after_vmafence(vma_type); + } + # else, silently do nothing - } else if ((rs1 == 0) && (rs2 != 0)) { - # invalidates all translations from ASID 'asid' - # does not affect global mappings + } else { + # invalidate all translations from leaf page tables for address space 'asid' containing 'vaddr' + # does not affect global mappings + if (canonical_vaddr?(vaddr)) { vma_type.single_asid = true; vma_type.asid = asid; + vma_type.single_vaddr = true; + vma_type.vaddr = vaddr; order_pgtbl_writes_before_vmafence(vma_type); invalidate_translations(vma_type); order_pgtbl_reads_after_vmafence(vma_type); - - } else if ((rs1 != 0) && (rs2 == 0)) { - # invalidate all translations from leaf page tables containing 'vaddr' - # does not affect global mappings - if (canonical_vaddr?(vaddr)) { - vma_type.single_vaddr = true; - vma_type.vaddr = vaddr; - - order_pgtbl_writes_before_vmafence(vma_type); - invalidate_translations(vma_type); - order_pgtbl_reads_after_vmafence(vma_type); - } - # else, silently do nothing - - } else { - # invalidate all translations from leaf page tables for address space 'asid' containing 'vaddr' - # does not affect global mappings - if (canonical_vaddr?(vaddr)) { - vma_type.single_asid = true; - vma_type.asid = asid; - vma_type.single_vaddr = true; - vma_type.vaddr = vaddr; - - order_pgtbl_writes_before_vmafence(vma_type); - invalidate_translations(vma_type); - order_pgtbl_reads_after_vmafence(vma_type); - } - # else, silently do nothing } + # else, silently do nothing + } + + + +sail(): | + { + let addr : option(xlenbits) = if rs1 == 0b00000 then None() else Some(X(rs1)); + let asid : option(xlenbits) = if rs2 == 0b00000 then None() else Some(X(rs2)); + match cur_privilege { + User => { handle_illegal(); RETIRE_FAIL }, + Supervisor => match (architecture(get_mstatus_SXL(mstatus)), mstatus.TVM()) { + (Some(_), 0b1) => { handle_illegal(); RETIRE_FAIL }, + (Some(_), 0b0) => { flush_TLB(asid, addr); RETIRE_SUCCESS }, + (_, _) => internal_error(__FILE__, __LINE__, "unimplemented sfence architecture") + }, + Machine => { flush_TLB(asid, addr); RETIRE_SUCCESS } + } + } - sail(): | - { - let addr : option(xlenbits) = if rs1 == 0b00000 then None() else Some(X(rs1)); - let asid : option(xlenbits) = if rs2 == 0b00000 then None() else Some(X(rs2)); - match cur_privilege { - User => { handle_illegal(); RETIRE_FAIL }, - Supervisor => match (architecture(get_mstatus_SXL(mstatus)), mstatus.TVM()) { - (Some(_), 0b1) => { handle_illegal(); RETIRE_FAIL }, - (Some(_), 0b0) => { flush_TLB(asid, addr); RETIRE_SUCCESS }, - (_, _) => internal_error(__FILE__, __LINE__, "unimplemented sfence architecture") - }, - Machine => { flush_TLB(asid, addr); RETIRE_SUCCESS } - } - } - - - diff --git a/arch/inst/S/sret.yaml b/arch/inst/S/sret.yaml index 1d5dad224..f4a3f09e6 100644 --- a/arch/inst/S/sret.yaml +++ b/arch/inst/S/sret.yaml @@ -1,147 +1,149 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sret: - long_name: Supervisor Exception Return - description: | - Returns from an exception. - - When `sret` is allowed to execute, its behavior depends on whether or not the current privilege - mode is virtualized. - - *When the current privlege mode is (H)S-mode or M-mode* - - `sret` sets `hstatus.HPV` = 0, `mstatus.SPP` = 0, - `mstatus.SIE` = `mstatus.SPIE`, and `mstatus.SPIE` = 1, - changes the privlege mode according to the table below, - and then jumps to the address in `sepc`. - - .Next privilege mode following an `sret` in (H)S-mode or M-mode - [%autowidth] - |=== - | [.rotate]#`mstatus.SPP`# | [.rotate]#`hstatus.SPV`# .>| Mode after `sret` - - | 0 | 0 | U-mode - | 0 | 1 | VU-mode - | 1 | 0 | (H)S-mode - | 1 | 1 | VS-mode - |=== - - *When the current privlege mode is VS-mode* - - `sret` sets - `vsstatus.SPP` = 0, `vsstatus.SIE` = `vstatus.SPIE`, and `vsstatus.SPIE` = 1, - changes the privlege mode according to the table below, - and then jumps to the address in `vsepc`. - - .Next privilege mode following an `sret` in (H)S-mode or M-mode - [%autowidth] - |=== - | [.rotate]#`vsstatus.SPP`# .>| Mode after `sret` - - | 0 | VU-mode - | 1 | VS-mode - |=== - - definedBy: S - assembly: "" - encoding: - match: '00010000001000000000000001110011' - access: - s: sometimes - u: never - vs: sometimes - vu: never - access_detail: | - Access is determined as follows: - - [%autowidth] - |=== - .2+| [.rotate]#`mstatus.TSR`# .2+| [.rotate]#`hstatus.VTSR`# 5+^.>| Behavior when executed from: - h| M-mode h| U-mode h| (H)S-mode h| VU-mode h| VS-mode - - | 0 | 0 | executes | `Illegal Instruction` | executes | `Virtual Instruction` | executes - | 0 | 1 | executes | `Illegal Instruction` | executes | `Virtual Instruction` | `Virtual Instruction` - | 1 | 0 | executes | `Illegal Instruction` | `Illegal Instruction` | `Virtual Instruction` | executes - | 1 | 1 | executes | `Illegal Instruction` | `Illegal Instruction` | `Virtual Instruction` | `Virtual Instruction` - |=== - operation(): | - # first, check access requirements - if (implemented?(ExtensionName::H)) { - if (CSR[mstatus].TSR == 1'b0 && CSR[hstatus].VTSR == 1'b0) { - if (mode() == PrivilegeMode::U) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } else if (mode() == PrivilegeMode::VU) { - raise (ExceptionCode::VirtualInstruction, mode(), $encoding); - } - } else if (CSR[mstatus].TSR == 1'b0 && CSR[hstatus].VTSR == 1'b1) { - if (mode() == PrivilegeMode::U) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } else if (mode() == PrivilegeMode::VU || mode() == PrivilegeMode::VS) { - raise (ExceptionCode::VirtualInstruction, mode(), $encoding); - } - } else if (CSR[mstatus].TSR == 1'b1 && CSR[hstatus].VTSR == 1'b0) { - if (mode() == PrivilegeMode::U || mode() == PrivilegeMode::S) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } else if (mode() == PrivilegeMode::VU) { - raise (ExceptionCode::VirtualInstruction, mode(), $encoding); - } - } else if (CSR[mstatus].TSR == 1'b1 && CSR[hstatus].VTSR == 1'b1) { - if (mode() == PrivilegeMode::U || mode() == PrivilegeMode::S) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } else if (mode() == PrivilegeMode::VU || mode() == PrivilegeMode::VS) { - raise (ExceptionCode::VirtualInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: sret +long_name: Supervisor Exception Return +description: | + Returns from an exception. + + When `sret` is allowed to execute, its behavior depends on whether or not the current privilege + mode is virtualized. + + *When the current privlege mode is (H)S-mode or M-mode* + + `sret` sets `hstatus.HPV` = 0, `mstatus.SPP` = 0, + `mstatus.SIE` = `mstatus.SPIE`, and `mstatus.SPIE` = 1, + changes the privlege mode according to the table below, + and then jumps to the address in `sepc`. + + .Next privilege mode following an `sret` in (H)S-mode or M-mode + [%autowidth] + |=== + | [.rotate]#`mstatus.SPP`# | [.rotate]#`hstatus.SPV`# .>| Mode after `sret` + + | 0 | 0 | U-mode + | 0 | 1 | VU-mode + | 1 | 0 | (H)S-mode + | 1 | 1 | VS-mode + |=== + + *When the current privlege mode is VS-mode* + + `sret` sets + `vsstatus.SPP` = 0, `vsstatus.SIE` = `vstatus.SPIE`, and `vsstatus.SPIE` = 1, + changes the privlege mode according to the table below, + and then jumps to the address in `vsepc`. + + .Next privilege mode following an `sret` in (H)S-mode or M-mode + [%autowidth] + |=== + | [.rotate]#`vsstatus.SPP`# .>| Mode after `sret` + + | 0 | VU-mode + | 1 | VS-mode + |=== + +definedBy: S +assembly: "" +encoding: + match: '00010000001000000000000001110011' +access: + s: sometimes + u: never + vs: sometimes + vu: never +access_detail: | + Access is determined as follows: + + [%autowidth] + |=== + .2+| [.rotate]#`mstatus.TSR`# .2+| [.rotate]#`hstatus.VTSR`# 5+^.>| Behavior when executed from: + h| M-mode h| U-mode h| (H)S-mode h| VU-mode h| VS-mode + + | 0 | 0 | executes | `Illegal Instruction` | executes | `Virtual Instruction` | executes + | 0 | 1 | executes | `Illegal Instruction` | executes | `Virtual Instruction` | `Virtual Instruction` + | 1 | 0 | executes | `Illegal Instruction` | `Illegal Instruction` | `Virtual Instruction` | executes + | 1 | 1 | executes | `Illegal Instruction` | `Illegal Instruction` | `Virtual Instruction` | `Virtual Instruction` + |=== +operation(): | + # first, check access requirements + if (implemented?(ExtensionName::H)) { + if (CSR[mstatus].TSR == 1'b0 && CSR[hstatus].VTSR == 1'b0) { + if (mode() == PrivilegeMode::U) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } else if (mode() == PrivilegeMode::VU) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); + } + } else if (CSR[mstatus].TSR == 1'b0 && CSR[hstatus].VTSR == 1'b1) { + if (mode() == PrivilegeMode::U) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } else if (mode() == PrivilegeMode::VU || mode() == PrivilegeMode::VS) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); } - } else { - if (mode() != PrivilegeMode::U) { + } else if (CSR[mstatus].TSR == 1'b1 && CSR[hstatus].VTSR == 1'b0) { + if (mode() == PrivilegeMode::U || mode() == PrivilegeMode::S) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } else if (mode() == PrivilegeMode::VU) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); } + } else if (CSR[mstatus].TSR == 1'b1 && CSR[hstatus].VTSR == 1'b1) { + if (mode() == PrivilegeMode::U || mode() == PrivilegeMode::S) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } else if (mode() == PrivilegeMode::VU || mode() == PrivilegeMode::VS) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); + } + } + } else { + if (mode() != PrivilegeMode::U) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } + } - # now pop the interrupt stack and change modes - if (!virtual_mode?()) { - if (implemented?(ExtensionName::H)) { - if (CSR[hstatus].SPV == 1'b1) { - if (CSR[mstatus].SPP == 2'b01) { - set_mode(PrivilegeMode::VS); - } else if (CSR[mstatus].SPP == 2'b00) { - set_mode(PrivilegeMode::VU); - } + # now pop the interrupt stack and change modes + if (!virtual_mode?()) { + if (implemented?(ExtensionName::H)) { + if (CSR[hstatus].SPV == 1'b1) { + if (CSR[mstatus].SPP == 2'b01) { + set_mode(PrivilegeMode::VS); + } else if (CSR[mstatus].SPP == 2'b00) { + set_mode(PrivilegeMode::VU); } - CSR[hstatus].SPV = 0; - } - CSR[mstatus].SIE = CSR[mstatus].SPIE; - CSR[mstatus].SPIE = 1; - CSR[mstatus].SPP = 2'b00; - $pc = $bits(CSR[sepc]); - } else { - if (CSR[mstatus].TSR == 1'b1) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } - CSR[vsstatus].SPP = 0; - CSR[vsstatus].SIE = CSR[vsstatus].SPIE; - CSR[vsstatus].SPIE = 1; - $pc = $bits(CSR[vsepc]); + CSR[hstatus].SPV = 0; + } + CSR[mstatus].SIE = CSR[mstatus].SPIE; + CSR[mstatus].SPIE = 1; + CSR[mstatus].SPP = 2'b00; + $pc = $bits(CSR[sepc]); + } else { + if (CSR[mstatus].TSR == 1'b1) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + CSR[vsstatus].SPP = 0; + CSR[vsstatus].SIE = CSR[vsstatus].SPIE; + CSR[vsstatus].SPIE = 1; + $pc = $bits(CSR[vsepc]); + } + + +sail(): | + { + let sret_illegal : bool = match cur_privilege { + User => true, + Supervisor => not(haveSupMode ()) | mstatus.TSR() == 0b1, + Machine => not(haveSupMode ()) + }; + if sret_illegal + then { handle_illegal(); RETIRE_FAIL } + else if not(ext_check_xret_priv (Supervisor)) + then { ext_fail_xret_priv(); RETIRE_FAIL } + else { + set_next_pc(exception_handler(cur_privilege, CTL_SRET(), PC)); + RETIRE_SUCCESS } + } - sail(): | - { - let sret_illegal : bool = match cur_privilege { - User => true, - Supervisor => not(haveSupMode ()) | mstatus.TSR() == 0b1, - Machine => not(haveSupMode ()) - }; - if sret_illegal - then { handle_illegal(); RETIRE_FAIL } - else if not(ext_check_xret_priv (Supervisor)) - then { ext_fail_xret_priv(); RETIRE_FAIL } - else { - set_next_pc(exception_handler(cur_privilege, CTL_SRET(), PC)); - RETIRE_SUCCESS - } - } - - diff --git a/arch/inst/Svinval/hinval.gvma.yaml b/arch/inst/Svinval/hinval.gvma.yaml index 8283ac6aa..5e5da1154 100644 --- a/arch/inst/Svinval/hinval.gvma.yaml +++ b/arch/inst/Svinval/hinval.gvma.yaml @@ -1,86 +1,88 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hinval.gvma: - long_name: Invalidate cached address translations - definedBy: - allOf: - - Svinval - - H - encoding: - match: 0110011----------000000001110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - description: | - `hinval.gvma` has the same semantics as `sinval.vma` except that it combines with - `sfence.w.inval` and `sfence.inval.ir` to replace `hfence.gvma` and uses VMID instead of ASID. - access: - s: sometimes - u: never - vs: never - vu: never - assembly: xs1, xs2 - operation(): | - XReg gpa = X[rs1]; - Bits vmid = X[rs2][VMID_WIDTH-1:0]; +$schema: "inst_schema.json#" +kind: instruction +name: hinval.gvma +long_name: Invalidate cached address translations +definedBy: + allOf: + - Svinval + - H +encoding: + match: 0110011----------000000001110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +description: | + `hinval.gvma` has the same semantics as `sinval.vma` except that it combines with + `sfence.w.inval` and `sfence.inval.ir` to replace `hfence.gvma` and uses VMID instead of ASID. +access: + s: sometimes + u: never + vs: never + vu: never +assembly: xs1, xs2 +operation(): | + XReg gpa = X[rs1]; + Bits vmid = X[rs2][VMID_WIDTH-1:0]; - if (mode() == PrivilegeMode::U) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + if (mode() == PrivilegeMode::U) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - if (CSR[mstatus].TVM == 1 && mode() == PrivilegeMode::S) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + if (CSR[mstatus].TVM == 1 && mode() == PrivilegeMode::S) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - if ((mode() == PrivilegeMode::VS) || (mode() == PrivilegeMode::VU)) { - raise (ExceptionCode::VirtualInstruction, mode(), $encoding); - } + if ((mode() == PrivilegeMode::VS) || (mode() == PrivilegeMode::VU)) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); + } - # note: this will default to "all" - VmaOrderType vma_type; - vma_type.gstage = true; + # note: this will default to "all" + VmaOrderType vma_type; + vma_type.gstage = true; - if ((rs1 == 0) && (rs2 == 0)) { - # invalidate all G-stage translations, from all addresses and all VMIDs - # includes global mappings - vma_type.global = true; + if ((rs1 == 0) && (rs2 == 0)) { + # invalidate all G-stage translations, from all addresses and all VMIDs + # includes global mappings + vma_type.global = true; - invalidate_translations(vma_type); + invalidate_translations(vma_type); - } else if ((rs1 == 0) && (rs2 != 0)) { - # invalidates all G-stage translations from VMID 'vmid' - # does not affect global mappings - vma_type.single_vmid = true; - vma_type.vmid = vmid; + } else if ((rs1 == 0) && (rs2 != 0)) { + # invalidates all G-stage translations from VMID 'vmid' + # does not affect global mappings + vma_type.single_vmid = true; + vma_type.vmid = vmid; - invalidate_translations(vma_type); + invalidate_translations(vma_type); - } else if ((rs1 != 0) && (rs2 == 0)) { - # invalidate all G-stage translations from leaf page tables containing 'vaddr' - # does not affect global mappings - if (canonical_gpaddr?(gpa)) { - vma_type.single_gpaddr = true; - vma_type.gpaddr = gpa; + } else if ((rs1 != 0) && (rs2 == 0)) { + # invalidate all G-stage translations from leaf page tables containing 'vaddr' + # does not affect global mappings + if (canonical_gpaddr?(gpa)) { + vma_type.single_gpaddr = true; + vma_type.gpaddr = gpa; - invalidate_translations(vma_type); + invalidate_translations(vma_type); - } - # else, silently do nothing + } + # else, silently do nothing - } else { - # invalidate all G-stage translations from leaf page tables for virtual machine 'vmid' containing 'vaddr' - # does not affect global mappings - if (canonical_gpaddr?(gpa)) { - vma_type.single_vmid = true; - vma_type.vmid = vmid; - vma_type.single_gpaddr = true; - vma_type.gpaddr = gpa; + } else { + # invalidate all G-stage translations from leaf page tables for virtual machine 'vmid' containing 'vaddr' + # does not affect global mappings + if (canonical_gpaddr?(gpa)) { + vma_type.single_vmid = true; + vma_type.vmid = vmid; + vma_type.single_gpaddr = true; + vma_type.gpaddr = gpa; - invalidate_translations(vma_type); + invalidate_translations(vma_type); - } - # else, silently do nothing } - \ No newline at end of file + # else, silently do nothing + } + \ No newline at end of file diff --git a/arch/inst/Svinval/hinval.vvma.yaml b/arch/inst/Svinval/hinval.vvma.yaml index eade8e9d7..f987382aa 100644 --- a/arch/inst/Svinval/hinval.vvma.yaml +++ b/arch/inst/Svinval/hinval.vvma.yaml @@ -1,86 +1,88 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -hinval.vvma: - long_name: Invalidate cached address translations - definedBy: - allOf: - - Svinval - - H - encoding: - match: 0010011----------000000001110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - description: | - `hinval.vvma` has the same semantics as `sinval.vma` except that it combines with - `sfence.w.inval` and `sfence.inval.ir` to replace `hfence.vvma`. - access: - s: always - u: never - vs: never - vu: never - assembly: xs1, xs2 - operation(): | - XReg vaddr = X[rs1]; - Bits asid = X[rs2][ASID_WIDTH-1:0]; - Bits vmid = CSR[hgatp].VMID; +$schema: "inst_schema.json#" +kind: instruction +name: hinval.vvma +long_name: Invalidate cached address translations +definedBy: + allOf: + - Svinval + - H +encoding: + match: 0010011----------000000001110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +description: | + `hinval.vvma` has the same semantics as `sinval.vma` except that it combines with + `sfence.w.inval` and `sfence.inval.ir` to replace `hfence.vvma`. +access: + s: always + u: never + vs: never + vu: never +assembly: xs1, xs2 +operation(): | + XReg vaddr = X[rs1]; + Bits asid = X[rs2][ASID_WIDTH-1:0]; + Bits vmid = CSR[hgatp].VMID; - if (mode() == PrivilegeMode::U) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } + if (mode() == PrivilegeMode::U) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - if ((CSR[misa].H == 1) && - (mode() == PrivilegeMode::VS || mode() == PrivilegeMode::VU)) { - raise (ExceptionCode::VirtualInstruction, mode(), $encoding); - } + if ((CSR[misa].H == 1) && + (mode() == PrivilegeMode::VS || mode() == PrivilegeMode::VU)) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); + } - # note: this will default to "all" - VmaOrderType vma_type; - vma_type.vsmode = true; - vma_type.single_vmid = true; - vma_type.vmid = vmid; + # note: this will default to "all" + VmaOrderType vma_type; + vma_type.vsmode = true; + vma_type.single_vmid = true; + vma_type.vmid = vmid; - if ((rs1 == 0) && (rs2 == 0)) { - # invalidate all translations, from all addresses and all ASIDs - # includes global mappings - vma_type.global = true; + if ((rs1 == 0) && (rs2 == 0)) { + # invalidate all translations, from all addresses and all ASIDs + # includes global mappings + vma_type.global = true; - invalidate_translations(vma_type); + invalidate_translations(vma_type); - } else if ((rs1 == 0) && (rs2 != 0)) { - # invalidates all translations from ASID 'asid' - # does not affect global mappings - vma_type.single_asid = true; - vma_type.asid = asid; + } else if ((rs1 == 0) && (rs2 != 0)) { + # invalidates all translations from ASID 'asid' + # does not affect global mappings + vma_type.single_asid = true; + vma_type.asid = asid; - invalidate_translations(vma_type); + invalidate_translations(vma_type); - } else if ((rs1 != 0) && (rs2 == 0)) { - # invalidate all translations from leaf page tables containing 'vaddr' - # does not affect global mappings - if (canonical_vaddr?(vaddr)) { - vma_type.single_vaddr = true; - vma_type.vaddr = vaddr; + } else if ((rs1 != 0) && (rs2 == 0)) { + # invalidate all translations from leaf page tables containing 'vaddr' + # does not affect global mappings + if (canonical_vaddr?(vaddr)) { + vma_type.single_vaddr = true; + vma_type.vaddr = vaddr; - invalidate_translations(vma_type); + invalidate_translations(vma_type); - } - # else, silently do nothing + } + # else, silently do nothing - } else { - # invalidate all translations from leaf page tables for address space 'asid' containing 'vaddr' - # does not affect global mappings - if (canonical_vaddr?(vaddr)) { - vma_type.single_asid = true; - vma_type.asid = asid; - vma_type.single_vaddr = true; - vma_type.vaddr = vaddr; + } else { + # invalidate all translations from leaf page tables for address space 'asid' containing 'vaddr' + # does not affect global mappings + if (canonical_vaddr?(vaddr)) { + vma_type.single_asid = true; + vma_type.asid = asid; + vma_type.single_vaddr = true; + vma_type.vaddr = vaddr; - invalidate_translations(vma_type); + invalidate_translations(vma_type); - } - # else, silently do nothing } - \ No newline at end of file + # else, silently do nothing + } + \ No newline at end of file diff --git a/arch/inst/Svinval/sfence.inval.ir.yaml b/arch/inst/Svinval/sfence.inval.ir.yaml index c60e66a8d..6b1c993ce 100644 --- a/arch/inst/Svinval/sfence.inval.ir.yaml +++ b/arch/inst/Svinval/sfence.inval.ir.yaml @@ -1,37 +1,39 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sfence.inval.ir: - long_name: Order implicit page table reads after invalidation - definedBy: Svinval - encoding: - match: "00011000000100000000000001110011" - description: | - The `sfence.inval.ir` instruction guarantees that any previous `sinval.vma` - instructions executed by the current hart are ordered before subsequent implicit references by - that hart to the memory-management data structures. - access: - s: sometimes - u: never - vs: sometimes - vu: never - assembly: "" - operation(): | - if (mode() == PrivilegeMode::U) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: sfence.inval.ir +long_name: Order implicit page table reads after invalidation +definedBy: Svinval +encoding: + match: "00011000000100000000000001110011" +description: | + The `sfence.inval.ir` instruction guarantees that any previous `sinval.vma` + instructions executed by the current hart are ordered before subsequent implicit references by + that hart to the memory-management data structures. +access: + s: sometimes + u: never + vs: sometimes + vu: never +assembly: "" +operation(): | + if (mode() == PrivilegeMode::U) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - if (CSR[misa].H == 1 && mode() == PrivilegeMode::VU) { - raise (ExceptionCode::VirtualInstruction, mode(), $encoding); - } + if (CSR[misa].H == 1 && mode() == PrivilegeMode::VU) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); + } - # order all subsequent (implicit) loads after an sfence/hfence invalidation - # Unlike SFENCE.VMA/HFENCE.[GV]VMA, SFENCE.W.INVAL is indiscriminate; - # it orders all reads after all page tables - VmaOrderType vma_type; - vma_type.global = true; - vma_type.smode = true; - if (CSR[misa].H == 1) { - vma_type.vsmode = true; - vma_type.gstage = true; - } - order_pgtbl_reads_after_vmafence(vma_type); + # order all subsequent (implicit) loads after an sfence/hfence invalidation + # Unlike SFENCE.VMA/HFENCE.[GV]VMA, SFENCE.W.INVAL is indiscriminate; + # it orders all reads after all page tables + VmaOrderType vma_type; + vma_type.global = true; + vma_type.smode = true; + if (CSR[misa].H == 1) { + vma_type.vsmode = true; + vma_type.gstage = true; + } + order_pgtbl_reads_after_vmafence(vma_type); diff --git a/arch/inst/Svinval/sfence.w.inval.yaml b/arch/inst/Svinval/sfence.w.inval.yaml index 600b6887f..3927e4811 100644 --- a/arch/inst/Svinval/sfence.w.inval.yaml +++ b/arch/inst/Svinval/sfence.w.inval.yaml @@ -1,39 +1,41 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sfence.w.inval: - long_name: Order writes before sfence - definedBy: Svinval - encoding: - match: "00011000000000000000000001110011" - description: | - The `sfence.w.inval` instruction guarantees that any previous stores already visible to the - current RISC-V hart are ordered before subsequent `sinval.vma` instructions executed by the - same hart. - access: - s: sometimes - u: never - vs: sometimes - vu: never - assembly: "" - operation(): | - if (mode() == PrivilegeMode::U) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: sfence.w.inval +long_name: Order writes before sfence +definedBy: Svinval +encoding: + match: "00011000000000000000000001110011" +description: | + The `sfence.w.inval` instruction guarantees that any previous stores already visible to the + current RISC-V hart are ordered before subsequent `sinval.vma` instructions executed by the + same hart. +access: + s: sometimes + u: never + vs: sometimes + vu: never +assembly: "" +operation(): | + if (mode() == PrivilegeMode::U) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } - if (CSR[misa].H == 1 && mode() == PrivilegeMode::VU) { - raise (ExceptionCode::VirtualInstruction, mode(), $encoding); - } + if (CSR[misa].H == 1 && mode() == PrivilegeMode::VU) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); + } - # order all prior stores already visible to the current hart - # before any following sfence - # Unlike SFENCE.VMA/HFENCE.[GV]VMA, SFENCE.W.INVAL is indiscriminate; - # it orders all writes before all page tables - VmaOrderType vma_type; - vma_type.global = true; - vma_type.smode = true; - if (CSR[misa].H == 1) { - vma_type.vsmode = true; - vma_type.gstage = true; - } - order_pgtbl_writes_before_vmafence(vma_type); + # order all prior stores already visible to the current hart + # before any following sfence + # Unlike SFENCE.VMA/HFENCE.[GV]VMA, SFENCE.W.INVAL is indiscriminate; + # it orders all writes before all page tables + VmaOrderType vma_type; + vma_type.global = true; + vma_type.smode = true; + if (CSR[misa].H == 1) { + vma_type.vsmode = true; + vma_type.gstage = true; + } + order_pgtbl_writes_before_vmafence(vma_type); \ No newline at end of file diff --git a/arch/inst/Svinval/sinval.vma.yaml b/arch/inst/Svinval/sinval.vma.yaml index 77f1c2fcb..4be763664 100644 --- a/arch/inst/Svinval/sinval.vma.yaml +++ b/arch/inst/Svinval/sinval.vma.yaml @@ -1,96 +1,98 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sinval.vma: - long_name: Invalidate cached address translations - definedBy: Svinval - encoding: - match: 0001011----------000000001110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - description: - The `sinval.vma` instruction invalidates any address-translation cache entries that an - `sfence.vma` instruction with the same values of rs1 and rs2 would invalidate. - However, unlike `sfence.vma`, `sinval.vma` instructions are only ordered with respect to - `sfence.vma`, `sfence.w.inval`, and `sfence.inval.ir` instructions as defined below. - access: - s: sometimes - u: never - vs: sometimes - vu: never - assembly: xs1, xs2 - operation(): | - XReg vaddr = X[rs1]; - Bits asid = X[rs2][ASID_WIDTH-1:0]; - - if (CSR[mstatus].TVM == 1 && - ((mode() == PrivilegeMode::S) || (mode() == PrivilegeMode::VS))) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - - if (CSR[misa].H == 1 && CSR[hstatus].VTVM == 1 && mode() == PrivilegeMode::VS) { - raise (ExceptionCode::VirtualInstruction, mode(), $encoding); - } - - if (mode() == PrivilegeMode::U) { - raise (ExceptionCode::IllegalInstruction, mode(), $encoding); - } +$schema: "inst_schema.json#" +kind: instruction +name: sinval.vma +long_name: Invalidate cached address translations +definedBy: Svinval +encoding: + match: 0001011----------000000001110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +description: + The `sinval.vma` instruction invalidates any address-translation cache entries that an + `sfence.vma` instruction with the same values of rs1 and rs2 would invalidate. + However, unlike `sfence.vma`, `sinval.vma` instructions are only ordered with respect to + `sfence.vma`, `sfence.w.inval`, and `sfence.inval.ir` instructions as defined below. +access: + s: sometimes + u: never + vs: sometimes + vu: never +assembly: xs1, xs2 +operation(): | + XReg vaddr = X[rs1]; + Bits asid = X[rs2][ASID_WIDTH-1:0]; + + if (CSR[mstatus].TVM == 1 && + ((mode() == PrivilegeMode::S) || (mode() == PrivilegeMode::VS))) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + if (CSR[misa].H == 1 && CSR[hstatus].VTVM == 1 && mode() == PrivilegeMode::VS) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); + } + + if (mode() == PrivilegeMode::U) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + if (CSR[misa].H == 1 && mode() == PrivilegeMode::VU) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); + } + + # note: this will default to "all" + VmaOrderType vma_type; + if (CSR[misa].H == 1 && mode() == PrivilegeMode::VS) { + vma_type.vsmode = true; + vma_type.single_vmid = true; + vma_type.vmid = CSR[hgatp].VMID; + } else { + vma_type.smode = true; + } + + if ((rs1 == 0) && (rs2 == 0)) { + # invalidate all translations, from all addresses and all ASIDs + # includes global mappings + vma_type.global = true; + + invalidate_translations(vma_type); + + } else if ((rs1 == 0) && (rs2 != 0)) { + # invalidates all translations from ASID 'asid' + # does not affect global mappings + vma_type.single_asid = true; + vma_type.asid = asid; + + invalidate_translations(vma_type); + + } else if ((rs1 != 0) && (rs2 == 0)) { + # invalidate all translations from leaf page tables containing 'vaddr' + # does not affect global mappings + if (canonical_vaddr?(vaddr)) { + vma_type.single_vaddr = true; + vma_type.vaddr = vaddr; - if (CSR[misa].H == 1 && mode() == PrivilegeMode::VU) { - raise (ExceptionCode::VirtualInstruction, mode(), $encoding); - } + invalidate_translations(vma_type); - # note: this will default to "all" - VmaOrderType vma_type; - if (CSR[misa].H == 1 && mode() == PrivilegeMode::VS) { - vma_type.vsmode = true; - vma_type.single_vmid = true; - vma_type.vmid = CSR[hgatp].VMID; - } else { - vma_type.smode = true; } + # else, silently do nothing - if ((rs1 == 0) && (rs2 == 0)) { - # invalidate all translations, from all addresses and all ASIDs - # includes global mappings - vma_type.global = true; - - invalidate_translations(vma_type); - - } else if ((rs1 == 0) && (rs2 != 0)) { - # invalidates all translations from ASID 'asid' - # does not affect global mappings + } else { + # invalidate all translations from leaf page tables for address space 'asid' containing 'vaddr' + # does not affect global mappings + if (canonical_vaddr?(vaddr)) { vma_type.single_asid = true; vma_type.asid = asid; + vma_type.single_vaddr = true; + vma_type.vaddr = vaddr; invalidate_translations(vma_type); - } else if ((rs1 != 0) && (rs2 == 0)) { - # invalidate all translations from leaf page tables containing 'vaddr' - # does not affect global mappings - if (canonical_vaddr?(vaddr)) { - vma_type.single_vaddr = true; - vma_type.vaddr = vaddr; - - invalidate_translations(vma_type); - - } - # else, silently do nothing - - } else { - # invalidate all translations from leaf page tables for address space 'asid' containing 'vaddr' - # does not affect global mappings - if (canonical_vaddr?(vaddr)) { - vma_type.single_asid = true; - vma_type.asid = asid; - vma_type.single_vaddr = true; - vma_type.vaddr = vaddr; - - invalidate_translations(vma_type); - - } - # else, silently do nothing } - \ No newline at end of file + # else, silently do nothing + } + \ No newline at end of file diff --git a/arch/inst/V/vaadd.vv.yaml b/arch/inst/V/vaadd.vv.yaml index b7533143d..329c014f9 100644 --- a/arch/inst/V/vaadd.vv.yaml +++ b/arch/inst/V/vaadd.vv.yaml @@ -1,109 +1,110 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaadd.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 001001-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaadd.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 001001-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), - MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), - MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VDIVU => { - let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - to_bits(SEW, q) - }, - MVV_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVV_VREMU => { - let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVV_VREM => { - let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), + MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), + MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VDIVU => { + let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + to_bits(SEW, q) + }, + MVV_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVV_VREMU => { + let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVV_VREM => { + let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vaadd.vx.yaml b/arch/inst/V/vaadd.vx.yaml index c62c2da70..12f3ab53c 100644 --- a/arch/inst/V/vaadd.vx.yaml +++ b/arch/inst/V/vaadd.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaadd.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001001-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaadd.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001001-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vaaddu.vv.yaml b/arch/inst/V/vaaddu.vv.yaml index 70d747182..08fc153ce 100644 --- a/arch/inst/V/vaaddu.vv.yaml +++ b/arch/inst/V/vaaddu.vv.yaml @@ -1,109 +1,110 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaaddu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 001000-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaaddu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 001000-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), - MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), - MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VDIVU => { - let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - to_bits(SEW, q) - }, - MVV_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVV_VREMU => { - let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVV_VREM => { - let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), + MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), + MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VDIVU => { + let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + to_bits(SEW, q) + }, + MVV_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVV_VREMU => { + let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVV_VREM => { + let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vaaddu.vx.yaml b/arch/inst/V/vaaddu.vx.yaml index 60b343335..e02ff1000 100644 --- a/arch/inst/V/vaaddu.vx.yaml +++ b/arch/inst/V/vaaddu.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaaddu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001000-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaaddu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001000-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vadc.vim.yaml b/arch/inst/V/vadc.vim.yaml index a1b3464d1..4979da49e 100644 --- a/arch/inst/V/vadc.vim.yaml +++ b/arch/inst/V/vadc.vim.yaml @@ -1,68 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vadc.vim: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vd, imm - encoding: - match: 0100000----------011-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vadc.vim +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vd, imm +encoding: + match: 0100000----------011-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - /* for bypassing normal masking in init_masked_result */ - vec_trues : vector('n, dec, bool) = undefined; - foreach (i from 0 to (num_elem - 1)) { - vec_trues[i] = true - }; - - let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vec_trues); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VIMS_VADC => to_bits(SEW, unsigned(vs2_val[i]) + unsigned(imm_val) + unsigned(bool_to_bits(vm_val[i]))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + /* for bypassing normal masking in init_masked_result */ + vec_trues : vector('n, dec, bool) = undefined; + foreach (i from 0 to (num_elem - 1)) { + vec_trues[i] = true + }; + + let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vec_trues); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VIMS_VADC => to_bits(SEW, unsigned(vs2_val[i]) + unsigned(imm_val) + unsigned(bool_to_bits(vm_val[i]))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vadc.vvm.yaml b/arch/inst/V/vadc.vvm.yaml index fbad144d5..db8e26b38 100644 --- a/arch/inst/V/vadc.vvm.yaml +++ b/arch/inst/V/vadc.vvm.yaml @@ -1,69 +1,70 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vadc.vvm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0100000----------000-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vadc.vvm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0100000----------000-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - /* for bypassing normal masking in init_masked_result */ - vec_trues : vector('n, dec, bool) = undefined; - foreach (i from 0 to (num_elem - 1)) { - vec_trues[i] = true - }; - - let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vec_trues); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VVMS_VADC => to_bits(SEW, unsigned(vs2_val[i]) + unsigned(vs1_val[i]) + unsigned(bool_to_bits(vm_val[i]))), - VVMS_VSBC => to_bits(SEW, unsigned(vs2_val[i]) - unsigned(vs1_val[i]) - unsigned(bool_to_bits(vm_val[i]))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + /* for bypassing normal masking in init_masked_result */ + vec_trues : vector('n, dec, bool) = undefined; + foreach (i from 0 to (num_elem - 1)) { + vec_trues[i] = true + }; + + let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vec_trues); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VVMS_VADC => to_bits(SEW, unsigned(vs2_val[i]) + unsigned(vs1_val[i]) + unsigned(bool_to_bits(vm_val[i]))), + VVMS_VSBC => to_bits(SEW, unsigned(vs2_val[i]) - unsigned(vs1_val[i]) - unsigned(bool_to_bits(vm_val[i]))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vadc.vxm.yaml b/arch/inst/V/vadc.vxm.yaml index e4cfaaaaa..939eee7f2 100644 --- a/arch/inst/V/vadc.vxm.yaml +++ b/arch/inst/V/vadc.vxm.yaml @@ -1,69 +1,70 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vadc.vxm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, xs1, vd - encoding: - match: 0100000----------100-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vadc.vxm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, xs1, vd +encoding: + match: 0100000----------100-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - /* for bypassing normal masking in init_masked_result */ - vec_trues : vector('n, dec, bool) = undefined; - foreach (i from 0 to (num_elem - 1)) { - vec_trues[i] = true - }; - - let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vec_trues); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VXMS_VADC => to_bits(SEW, unsigned(vs2_val[i]) + unsigned(rs1_val) + unsigned(bool_to_bits(vm_val[i]))), - VXMS_VSBC => to_bits(SEW, unsigned(vs2_val[i]) - unsigned(rs1_val) - unsigned(bool_to_bits(vm_val[i]))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + /* for bypassing normal masking in init_masked_result */ + vec_trues : vector('n, dec, bool) = undefined; + foreach (i from 0 to (num_elem - 1)) { + vec_trues[i] = true + }; + + let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vec_trues); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VXMS_VADC => to_bits(SEW, unsigned(vs2_val[i]) + unsigned(rs1_val) + unsigned(bool_to_bits(vm_val[i]))), + VXMS_VSBC => to_bits(SEW, unsigned(vs2_val[i]) - unsigned(rs1_val) - unsigned(bool_to_bits(vm_val[i]))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vadd.vi.yaml b/arch/inst/V/vadd.vi.yaml index c4f9878d9..f0246118a 100644 --- a/arch/inst/V/vadd.vi.yaml +++ b/arch/inst/V/vadd.vi.yaml @@ -1,94 +1,95 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vadd.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 000000-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vadd.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 000000-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VADD => vs2_val[i] + imm_val, - VI_VRSUB => imm_val - vs2_val[i], - VI_VAND => vs2_val[i] & imm_val, - VI_VOR => vs2_val[i] | imm_val, - VI_VXOR => vs2_val[i] ^ imm_val, - VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), - VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), - VI_VSLL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] << shift_amount - }, - VI_VSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] >> shift_amount - }, - VI_VSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VI_VSSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VI_VSSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VADD => vs2_val[i] + imm_val, + VI_VRSUB => imm_val - vs2_val[i], + VI_VAND => vs2_val[i] & imm_val, + VI_VOR => vs2_val[i] | imm_val, + VI_VXOR => vs2_val[i] ^ imm_val, + VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), + VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), + VI_VSLL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] << shift_amount + }, + VI_VSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] >> shift_amount + }, + VI_VSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VI_VSSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VI_VSSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vadd.vv.yaml b/arch/inst/V/vadd.vv.yaml index 9de339592..94fc3d0f3 100644 --- a/arch/inst/V/vadd.vv.yaml +++ b/arch/inst/V/vadd.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vadd.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000000-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vadd.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000000-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vadd.vx.yaml b/arch/inst/V/vadd.vx.yaml index f76479869..4067105f1 100644 --- a/arch/inst/V/vadd.vx.yaml +++ b/arch/inst/V/vadd.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vadd.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000000-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vadd.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000000-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vand.vi.yaml b/arch/inst/V/vand.vi.yaml index e29e07bef..eabfb2a01 100644 --- a/arch/inst/V/vand.vi.yaml +++ b/arch/inst/V/vand.vi.yaml @@ -1,94 +1,95 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vand.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 001001-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vand.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 001001-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VADD => vs2_val[i] + imm_val, - VI_VRSUB => imm_val - vs2_val[i], - VI_VAND => vs2_val[i] & imm_val, - VI_VOR => vs2_val[i] | imm_val, - VI_VXOR => vs2_val[i] ^ imm_val, - VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), - VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), - VI_VSLL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] << shift_amount - }, - VI_VSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] >> shift_amount - }, - VI_VSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VI_VSSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VI_VSSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VADD => vs2_val[i] + imm_val, + VI_VRSUB => imm_val - vs2_val[i], + VI_VAND => vs2_val[i] & imm_val, + VI_VOR => vs2_val[i] | imm_val, + VI_VXOR => vs2_val[i] ^ imm_val, + VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), + VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), + VI_VSLL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] << shift_amount + }, + VI_VSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] >> shift_amount + }, + VI_VSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VI_VSSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VI_VSSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vand.vv.yaml b/arch/inst/V/vand.vv.yaml index b20ec626e..2efc4a5a0 100644 --- a/arch/inst/V/vand.vv.yaml +++ b/arch/inst/V/vand.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vand.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 001001-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vand.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 001001-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vand.vx.yaml b/arch/inst/V/vand.vx.yaml index 6cdae6f34..a0ba15ec1 100644 --- a/arch/inst/V/vand.vx.yaml +++ b/arch/inst/V/vand.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vand.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001001-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vand.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001001-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vasub.vv.yaml b/arch/inst/V/vasub.vv.yaml index 06cb3c8dd..fd156c277 100644 --- a/arch/inst/V/vasub.vv.yaml +++ b/arch/inst/V/vasub.vv.yaml @@ -1,109 +1,110 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vasub.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 001011-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vasub.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 001011-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), - MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), - MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VDIVU => { - let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - to_bits(SEW, q) - }, - MVV_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVV_VREMU => { - let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVV_VREM => { - let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), + MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), + MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VDIVU => { + let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + to_bits(SEW, q) + }, + MVV_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVV_VREMU => { + let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVV_VREM => { + let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vasub.vx.yaml b/arch/inst/V/vasub.vx.yaml index 42ec9db66..b884f3844 100644 --- a/arch/inst/V/vasub.vx.yaml +++ b/arch/inst/V/vasub.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vasub.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001011-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vasub.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001011-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vasubu.vv.yaml b/arch/inst/V/vasubu.vv.yaml index 123783b1a..1597f0864 100644 --- a/arch/inst/V/vasubu.vv.yaml +++ b/arch/inst/V/vasubu.vv.yaml @@ -1,109 +1,110 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vasubu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 001010-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vasubu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 001010-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), - MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), - MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VDIVU => { - let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - to_bits(SEW, q) - }, - MVV_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVV_VREMU => { - let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVV_VREM => { - let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), + MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), + MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VDIVU => { + let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + to_bits(SEW, q) + }, + MVV_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVV_VREMU => { + let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVV_VREM => { + let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vasubu.vx.yaml b/arch/inst/V/vasubu.vx.yaml index 9261db522..7f6f2ee4b 100644 --- a/arch/inst/V/vasubu.vx.yaml +++ b/arch/inst/V/vasubu.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vasubu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001010-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vasubu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001010-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vcompress.vm.yaml b/arch/inst/V/vcompress.vm.yaml index 08c77eb8f..b997ea0f3 100644 --- a/arch/inst/V/vcompress.vm.yaml +++ b/arch/inst/V/vcompress.vm.yaml @@ -1,78 +1,79 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vcompress.vm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0101111----------010-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vcompress.vm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0101111----------010-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let start_element = get_start_element(); - let end_element = get_end_element(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - /* vcompress should always be executed with a vstart of 0 */ - if start_element != 0 | vs1 == vd | vs2 == vd | illegal_vd_unmasked() - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - - /* body elements */ - vd_idx : nat = 0; - foreach (i from 0 to (num_elem - 1)) { - if i <= end_element then { - if vs1_val[i] then { - let 'p = vd_idx; - assert('p < 'n); - result['p] = vs2_val[i]; - vd_idx = vd_idx + 1; - } +sail(): | + { + let start_element = get_start_element(); + let end_element = get_end_element(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + /* vcompress should always be executed with a vstart of 0 */ + if start_element != 0 | vs1 == vd | vs2 == vd | illegal_vd_unmasked() + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + + /* body elements */ + vd_idx : nat = 0; + foreach (i from 0 to (num_elem - 1)) { + if i <= end_element then { + if vs1_val[i] then { + let 'p = vd_idx; + assert('p < 'n); + result['p] = vs2_val[i]; + vd_idx = vd_idx + 1; } - }; - /* tail elements */ - if vd_idx < num_elem then { - let tail_ag : agtype = get_vtype_vta(); - let 'p = vd_idx; - foreach (i from 'p to (num_elem - 1)) { - result[i] = match tail_ag { - UNDISTURBED => vd_val[i], - AGNOSTIC => vd_val[i] /* TODO: configuration support */ - } + } + }; + /* tail elements */ + if vd_idx < num_elem then { + let tail_ag : agtype = get_vtype_vta(); + let 'p = vd_idx; + foreach (i from 'p to (num_elem - 1)) { + result[i] = match tail_ag { + UNDISTURBED => vd_val[i], + AGNOSTIC => vd_val[i] /* TODO: configuration support */ } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vcpop.m.yaml b/arch/inst/V/vcpop.m.yaml index abd41f5d1..788cfbadf 100644 --- a/arch/inst/V/vcpop.m.yaml +++ b/arch/inst/V/vcpop.m.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vcpop.m: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xd - encoding: - match: 010000------10000010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vcpop.m +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xd +encoding: + match: 010000------10000010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vdiv.vv.yaml b/arch/inst/V/vdiv.vv.yaml index c06bfccbd..668b545cd 100644 --- a/arch/inst/V/vdiv.vv.yaml +++ b/arch/inst/V/vdiv.vv.yaml @@ -1,109 +1,110 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vdiv.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100001-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vdiv.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100001-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), - MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), - MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VDIVU => { - let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - to_bits(SEW, q) - }, - MVV_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVV_VREMU => { - let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVV_VREM => { - let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), + MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), + MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VDIVU => { + let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + to_bits(SEW, q) + }, + MVV_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVV_VREMU => { + let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVV_VREM => { + let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vdiv.vx.yaml b/arch/inst/V/vdiv.vx.yaml index 2ed12950c..34dbf33f2 100644 --- a/arch/inst/V/vdiv.vx.yaml +++ b/arch/inst/V/vdiv.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vdiv.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100001-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vdiv.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100001-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vdivu.vv.yaml b/arch/inst/V/vdivu.vv.yaml index edbe82ffe..dad163f7a 100644 --- a/arch/inst/V/vdivu.vv.yaml +++ b/arch/inst/V/vdivu.vv.yaml @@ -1,109 +1,110 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vdivu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100000-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vdivu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100000-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), - MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), - MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VDIVU => { - let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - to_bits(SEW, q) - }, - MVV_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVV_VREMU => { - let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVV_VREM => { - let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), + MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), + MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VDIVU => { + let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + to_bits(SEW, q) + }, + MVV_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVV_VREMU => { + let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVV_VREM => { + let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vdivu.vx.yaml b/arch/inst/V/vdivu.vx.yaml index 374bb63e2..801e9f8eb 100644 --- a/arch/inst/V/vdivu.vx.yaml +++ b/arch/inst/V/vdivu.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vdivu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100000-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vdivu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100000-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfadd.vf.yaml b/arch/inst/V/vfadd.vf.yaml index bdb037380..218f5ca4c 100644 --- a/arch/inst/V/vfadd.vf.yaml +++ b/arch/inst/V/vfadd.vf.yaml @@ -1,85 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfadd.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000000-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfadd.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000000-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), - VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), - VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), - VF_VMIN => fp_min(vs2_val[i], rs1_val), - VF_VMAX => fp_max(vs2_val[i], rs1_val), - VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), - VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), - VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), - VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], - VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSLIDE1UP => { - if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - VF_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), + VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), + VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), + VF_VMIN => fp_min(vs2_val[i], rs1_val), + VF_VMAX => fp_max(vs2_val[i], rs1_val), + VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), + VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), + VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), + VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], + VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSLIDE1UP => { + if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + VF_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfadd.vv.yaml b/arch/inst/V/vfadd.vv.yaml index 1652ef809..3ece00bef 100644 --- a/arch/inst/V/vfadd.vv.yaml +++ b/arch/inst/V/vfadd.vv.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfadd.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000000-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfadd.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000000-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), - FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), - FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], - FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], - FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), + FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), + FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], + FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], + FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfclass.v.yaml b/arch/inst/V/vfclass.v.yaml index 2ef28967e..2feaae815 100644 --- a/arch/inst/V/vfclass.v.yaml +++ b/arch/inst/V/vfclass.v.yaml @@ -1,90 +1,91 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfclass.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010011------10000001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfclass.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010011------10000001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfunary1 { - FVV_VSQRT => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16Sqrt(rm_3b, vs2_val[i]), - 32 => riscv_f32Sqrt(rm_3b, vs2_val[i]), - 64 => riscv_f64Sqrt(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FVV_VRSQRT7 => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16Rsqrte7(rm_3b, vs2_val[i]), - 32 => riscv_f32Rsqrte7(rm_3b, vs2_val[i]), - 64 => riscv_f64Rsqrte7(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FVV_VREC7 => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16Recip7(rm_3b, vs2_val[i]), - 32 => riscv_f32Recip7(rm_3b, vs2_val[i]), - 64 => riscv_f64Recip7(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FVV_VCLASS => fp_class(vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfunary1 { + FVV_VSQRT => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16Sqrt(rm_3b, vs2_val[i]), + 32 => riscv_f32Sqrt(rm_3b, vs2_val[i]), + 64 => riscv_f64Sqrt(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FVV_VRSQRT7 => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16Rsqrte7(rm_3b, vs2_val[i]), + 32 => riscv_f32Rsqrte7(rm_3b, vs2_val[i]), + 64 => riscv_f64Rsqrte7(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FVV_VREC7 => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16Recip7(rm_3b, vs2_val[i]), + 32 => riscv_f32Recip7(rm_3b, vs2_val[i]), + 64 => riscv_f64Recip7(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FVV_VCLASS => fp_class(vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfcvt.f.x.v.yaml b/arch/inst/V/vfcvt.f.x.v.yaml index d67cf22e9..5e9165fc7 100644 --- a/arch/inst/V/vfcvt.f.x.v.yaml +++ b/arch/inst/V/vfcvt.f.x.v.yaml @@ -1,115 +1,116 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfcvt.f.x.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------00011001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfcvt.f.x.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------00011001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfunary0 { - FV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f32ToUi32(rm_3b, vs2_val[i]), - 64 => riscv_f64ToUi64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f32ToI32(rm_3b, vs2_val[i]), - 64 => riscv_f64ToI64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), - 32 => riscv_ui32ToF32(rm_3b, vs2_val[i]), - 64 => riscv_ui64ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), - 32 => riscv_i32ToF32(rm_3b, vs2_val[i]), - 64 => riscv_i64ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToUi16(0b001, vs2_val[i]), - 32 => riscv_f32ToUi32(0b001, vs2_val[i]), - 64 => riscv_f64ToUi64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToI16(0b001, vs2_val[i]), - 32 => riscv_f32ToI32(0b001, vs2_val[i]), - 64 => riscv_f64ToI64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfunary0 { + FV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f32ToUi32(rm_3b, vs2_val[i]), + 64 => riscv_f64ToUi64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f32ToI32(rm_3b, vs2_val[i]), + 64 => riscv_f64ToI64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), + 32 => riscv_ui32ToF32(rm_3b, vs2_val[i]), + 64 => riscv_ui64ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), + 32 => riscv_i32ToF32(rm_3b, vs2_val[i]), + 64 => riscv_i64ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToUi16(0b001, vs2_val[i]), + 32 => riscv_f32ToUi32(0b001, vs2_val[i]), + 64 => riscv_f64ToUi64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToI16(0b001, vs2_val[i]), + 32 => riscv_f32ToI32(0b001, vs2_val[i]), + 64 => riscv_f64ToI64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfcvt.f.xu.v.yaml b/arch/inst/V/vfcvt.f.xu.v.yaml index 62925a6c1..c4ea16e9e 100644 --- a/arch/inst/V/vfcvt.f.xu.v.yaml +++ b/arch/inst/V/vfcvt.f.xu.v.yaml @@ -1,115 +1,116 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfcvt.f.xu.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------00010001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfcvt.f.xu.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------00010001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfunary0 { - FV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f32ToUi32(rm_3b, vs2_val[i]), - 64 => riscv_f64ToUi64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f32ToI32(rm_3b, vs2_val[i]), - 64 => riscv_f64ToI64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), - 32 => riscv_ui32ToF32(rm_3b, vs2_val[i]), - 64 => riscv_ui64ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), - 32 => riscv_i32ToF32(rm_3b, vs2_val[i]), - 64 => riscv_i64ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToUi16(0b001, vs2_val[i]), - 32 => riscv_f32ToUi32(0b001, vs2_val[i]), - 64 => riscv_f64ToUi64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToI16(0b001, vs2_val[i]), - 32 => riscv_f32ToI32(0b001, vs2_val[i]), - 64 => riscv_f64ToI64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfunary0 { + FV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f32ToUi32(rm_3b, vs2_val[i]), + 64 => riscv_f64ToUi64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f32ToI32(rm_3b, vs2_val[i]), + 64 => riscv_f64ToI64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), + 32 => riscv_ui32ToF32(rm_3b, vs2_val[i]), + 64 => riscv_ui64ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), + 32 => riscv_i32ToF32(rm_3b, vs2_val[i]), + 64 => riscv_i64ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToUi16(0b001, vs2_val[i]), + 32 => riscv_f32ToUi32(0b001, vs2_val[i]), + 64 => riscv_f64ToUi64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToI16(0b001, vs2_val[i]), + 32 => riscv_f32ToI32(0b001, vs2_val[i]), + 64 => riscv_f64ToI64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfcvt.rtz.x.f.v.yaml b/arch/inst/V/vfcvt.rtz.x.f.v.yaml index cc6326783..e175d2caf 100644 --- a/arch/inst/V/vfcvt.rtz.x.f.v.yaml +++ b/arch/inst/V/vfcvt.rtz.x.f.v.yaml @@ -1,115 +1,116 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfcvt.rtz.x.f.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------00111001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfcvt.rtz.x.f.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------00111001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfunary0 { - FV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f32ToUi32(rm_3b, vs2_val[i]), - 64 => riscv_f64ToUi64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f32ToI32(rm_3b, vs2_val[i]), - 64 => riscv_f64ToI64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), - 32 => riscv_ui32ToF32(rm_3b, vs2_val[i]), - 64 => riscv_ui64ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), - 32 => riscv_i32ToF32(rm_3b, vs2_val[i]), - 64 => riscv_i64ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToUi16(0b001, vs2_val[i]), - 32 => riscv_f32ToUi32(0b001, vs2_val[i]), - 64 => riscv_f64ToUi64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToI16(0b001, vs2_val[i]), - 32 => riscv_f32ToI32(0b001, vs2_val[i]), - 64 => riscv_f64ToI64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfunary0 { + FV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f32ToUi32(rm_3b, vs2_val[i]), + 64 => riscv_f64ToUi64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f32ToI32(rm_3b, vs2_val[i]), + 64 => riscv_f64ToI64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), + 32 => riscv_ui32ToF32(rm_3b, vs2_val[i]), + 64 => riscv_ui64ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), + 32 => riscv_i32ToF32(rm_3b, vs2_val[i]), + 64 => riscv_i64ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToUi16(0b001, vs2_val[i]), + 32 => riscv_f32ToUi32(0b001, vs2_val[i]), + 64 => riscv_f64ToUi64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToI16(0b001, vs2_val[i]), + 32 => riscv_f32ToI32(0b001, vs2_val[i]), + 64 => riscv_f64ToI64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfcvt.rtz.xu.f.v.yaml b/arch/inst/V/vfcvt.rtz.xu.f.v.yaml index ccca0719e..dd94a1aa6 100644 --- a/arch/inst/V/vfcvt.rtz.xu.f.v.yaml +++ b/arch/inst/V/vfcvt.rtz.xu.f.v.yaml @@ -1,115 +1,116 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfcvt.rtz.xu.f.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------00110001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfcvt.rtz.xu.f.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------00110001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfunary0 { - FV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f32ToUi32(rm_3b, vs2_val[i]), - 64 => riscv_f64ToUi64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f32ToI32(rm_3b, vs2_val[i]), - 64 => riscv_f64ToI64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), - 32 => riscv_ui32ToF32(rm_3b, vs2_val[i]), - 64 => riscv_ui64ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), - 32 => riscv_i32ToF32(rm_3b, vs2_val[i]), - 64 => riscv_i64ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToUi16(0b001, vs2_val[i]), - 32 => riscv_f32ToUi32(0b001, vs2_val[i]), - 64 => riscv_f64ToUi64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToI16(0b001, vs2_val[i]), - 32 => riscv_f32ToI32(0b001, vs2_val[i]), - 64 => riscv_f64ToI64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfunary0 { + FV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f32ToUi32(rm_3b, vs2_val[i]), + 64 => riscv_f64ToUi64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f32ToI32(rm_3b, vs2_val[i]), + 64 => riscv_f64ToI64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), + 32 => riscv_ui32ToF32(rm_3b, vs2_val[i]), + 64 => riscv_ui64ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), + 32 => riscv_i32ToF32(rm_3b, vs2_val[i]), + 64 => riscv_i64ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToUi16(0b001, vs2_val[i]), + 32 => riscv_f32ToUi32(0b001, vs2_val[i]), + 64 => riscv_f64ToUi64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToI16(0b001, vs2_val[i]), + 32 => riscv_f32ToI32(0b001, vs2_val[i]), + 64 => riscv_f64ToI64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfcvt.x.f.v.yaml b/arch/inst/V/vfcvt.x.f.v.yaml index 5b1494819..afd39c892 100644 --- a/arch/inst/V/vfcvt.x.f.v.yaml +++ b/arch/inst/V/vfcvt.x.f.v.yaml @@ -1,115 +1,116 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfcvt.x.f.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------00001001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfcvt.x.f.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------00001001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfunary0 { - FV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f32ToUi32(rm_3b, vs2_val[i]), - 64 => riscv_f64ToUi64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f32ToI32(rm_3b, vs2_val[i]), - 64 => riscv_f64ToI64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), - 32 => riscv_ui32ToF32(rm_3b, vs2_val[i]), - 64 => riscv_ui64ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), - 32 => riscv_i32ToF32(rm_3b, vs2_val[i]), - 64 => riscv_i64ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToUi16(0b001, vs2_val[i]), - 32 => riscv_f32ToUi32(0b001, vs2_val[i]), - 64 => riscv_f64ToUi64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToI16(0b001, vs2_val[i]), - 32 => riscv_f32ToI32(0b001, vs2_val[i]), - 64 => riscv_f64ToI64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfunary0 { + FV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f32ToUi32(rm_3b, vs2_val[i]), + 64 => riscv_f64ToUi64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f32ToI32(rm_3b, vs2_val[i]), + 64 => riscv_f64ToI64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), + 32 => riscv_ui32ToF32(rm_3b, vs2_val[i]), + 64 => riscv_ui64ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), + 32 => riscv_i32ToF32(rm_3b, vs2_val[i]), + 64 => riscv_i64ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToUi16(0b001, vs2_val[i]), + 32 => riscv_f32ToUi32(0b001, vs2_val[i]), + 64 => riscv_f64ToUi64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToI16(0b001, vs2_val[i]), + 32 => riscv_f32ToI32(0b001, vs2_val[i]), + 64 => riscv_f64ToI64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfcvt.xu.f.v.yaml b/arch/inst/V/vfcvt.xu.f.v.yaml index ae6b9647c..a7c8b6148 100644 --- a/arch/inst/V/vfcvt.xu.f.v.yaml +++ b/arch/inst/V/vfcvt.xu.f.v.yaml @@ -1,115 +1,116 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfcvt.xu.f.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------00000001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfcvt.xu.f.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------00000001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfunary0 { - FV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f32ToUi32(rm_3b, vs2_val[i]), - 64 => riscv_f64ToUi64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f32ToI32(rm_3b, vs2_val[i]), - 64 => riscv_f64ToI64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), - 32 => riscv_ui32ToF32(rm_3b, vs2_val[i]), - 64 => riscv_ui64ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), - 32 => riscv_i32ToF32(rm_3b, vs2_val[i]), - 64 => riscv_i64ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToUi16(0b001, vs2_val[i]), - 32 => riscv_f32ToUi32(0b001, vs2_val[i]), - 64 => riscv_f64ToUi64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16ToI16(0b001, vs2_val[i]), - 32 => riscv_f32ToI32(0b001, vs2_val[i]), - 64 => riscv_f64ToI64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfunary0 { + FV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f32ToUi32(rm_3b, vs2_val[i]), + 64 => riscv_f64ToUi64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f32ToI32(rm_3b, vs2_val[i]), + 64 => riscv_f64ToI64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), + 32 => riscv_ui32ToF32(rm_3b, vs2_val[i]), + 64 => riscv_ui64ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), + 32 => riscv_i32ToF32(rm_3b, vs2_val[i]), + 64 => riscv_i64ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToUi16(0b001, vs2_val[i]), + 32 => riscv_f32ToUi32(0b001, vs2_val[i]), + 64 => riscv_f64ToUi64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16ToI16(0b001, vs2_val[i]), + 32 => riscv_f32ToI32(0b001, vs2_val[i]), + 64 => riscv_f64ToI64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfdiv.vf.yaml b/arch/inst/V/vfdiv.vf.yaml index 0c37c99f6..f46bae910 100644 --- a/arch/inst/V/vfdiv.vf.yaml +++ b/arch/inst/V/vfdiv.vf.yaml @@ -1,85 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfdiv.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100000-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfdiv.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100000-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), - VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), - VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), - VF_VMIN => fp_min(vs2_val[i], rs1_val), - VF_VMAX => fp_max(vs2_val[i], rs1_val), - VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), - VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), - VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), - VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], - VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSLIDE1UP => { - if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - VF_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), + VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), + VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), + VF_VMIN => fp_min(vs2_val[i], rs1_val), + VF_VMAX => fp_max(vs2_val[i], rs1_val), + VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), + VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), + VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), + VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], + VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSLIDE1UP => { + if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + VF_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfdiv.vv.yaml b/arch/inst/V/vfdiv.vv.yaml index 2e91f2a3f..10de2949a 100644 --- a/arch/inst/V/vfdiv.vv.yaml +++ b/arch/inst/V/vfdiv.vv.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfdiv.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100000-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfdiv.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100000-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), - FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), - FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], - FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], - FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), + FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), + FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], + FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], + FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfirst.m.yaml b/arch/inst/V/vfirst.m.yaml index 9199f55ee..e899e06e4 100644 --- a/arch/inst/V/vfirst.m.yaml +++ b/arch/inst/V/vfirst.m.yaml @@ -1,59 +1,60 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfirst.m: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xd - encoding: - match: 010000------10001010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfirst.m +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xd +encoding: + match: 010000------10001010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = unsigned(vlenb) * 8; - - if illegal_vd_unmasked() | not(assert_vstart(0)) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, 0, vs2_val, vm_val); - - index : int = -1; - foreach (i from 0 to (num_elem - 1)) { - if index == -1 then { - if mask[i] & vs2_val[i] then index = i; - }; +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = unsigned(vlenb) * 8; + + if illegal_vd_unmasked() | not(assert_vstart(0)) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, 0, vs2_val, vm_val); + + index : int = -1; + foreach (i from 0 to (num_elem - 1)) { + if index == -1 then { + if mask[i] & vs2_val[i] then index = i; }; - - X(rd) = to_bits(sizeof(xlen), index); - vstart = zeros(); - RETIRE_SUCCESS - } + }; - \ No newline at end of file + X(rd) = to_bits(sizeof(xlen), index); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmacc.vf.yaml b/arch/inst/V/vfmacc.vf.yaml index 68e5df409..99ce1b313 100644 --- a/arch/inst/V/vfmacc.vf.yaml +++ b/arch/inst/V/vfmacc.vf.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmacc.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101100-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmacc.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101100-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmacc.vv.yaml b/arch/inst/V/vfmacc.vv.yaml index 5d6803e30..b16c389a2 100644 --- a/arch/inst/V/vfmacc.vv.yaml +++ b/arch/inst/V/vfmacc.vv.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmacc.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101100-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmacc.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101100-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmadd.vf.yaml b/arch/inst/V/vfmadd.vf.yaml index 3376968fd..8ebc28dd0 100644 --- a/arch/inst/V/vfmadd.vf.yaml +++ b/arch/inst/V/vfmadd.vf.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmadd.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101000-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmadd.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101000-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmadd.vv.yaml b/arch/inst/V/vfmadd.vv.yaml index f304a8dc8..c4828106e 100644 --- a/arch/inst/V/vfmadd.vv.yaml +++ b/arch/inst/V/vfmadd.vv.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmadd.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101000-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmadd.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101000-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmax.vf.yaml b/arch/inst/V/vfmax.vf.yaml index ad23bb3df..552c300ef 100644 --- a/arch/inst/V/vfmax.vf.yaml +++ b/arch/inst/V/vfmax.vf.yaml @@ -1,85 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmax.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000110-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmax.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000110-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), - VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), - VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), - VF_VMIN => fp_min(vs2_val[i], rs1_val), - VF_VMAX => fp_max(vs2_val[i], rs1_val), - VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), - VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), - VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), - VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], - VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSLIDE1UP => { - if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - VF_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), + VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), + VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), + VF_VMIN => fp_min(vs2_val[i], rs1_val), + VF_VMAX => fp_max(vs2_val[i], rs1_val), + VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), + VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), + VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), + VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], + VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSLIDE1UP => { + if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + VF_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmax.vv.yaml b/arch/inst/V/vfmax.vv.yaml index 7f1a603e3..287666945 100644 --- a/arch/inst/V/vfmax.vv.yaml +++ b/arch/inst/V/vfmax.vv.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmax.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000110-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmax.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000110-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), - FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), - FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], - FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], - FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), + FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), + FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], + FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], + FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmerge.vfm.yaml b/arch/inst/V/vfmerge.vfm.yaml index 3a81e546a..254c60810 100644 --- a/arch/inst/V/vfmerge.vfm.yaml +++ b/arch/inst/V/vfmerge.vfm.yaml @@ -1,71 +1,72 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmerge.vfm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, xs1, vd - encoding: - match: 0101110----------101-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmerge.vfm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, xs1, vd +encoding: + match: 0101110----------101-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let start_element = get_start_element(); - let end_element = get_end_element(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); /* max(VLMAX,VLEN/SEW)) */ - let real_num_elem = if LMUL_pow >= 0 then num_elem else num_elem / (0 - LMUL_pow); /* VLMAX */ - - if illegal_fp_vd_masked(vd, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - - let tail_ag : agtype = get_vtype_vta(); - foreach (i from 0 to (num_elem - 1)) { - if i < start_element then { - result[i] = vd_val[i] - } else if i > end_element | i >= real_num_elem then { - result[i] = match tail_ag { - UNDISTURBED => vd_val[i], - AGNOSTIC => vd_val[i] /* TODO: configuration support */ - } - } else { - /* the merge operates on all body elements */ - result[i] = if vm_val[i] then rs1_val else vs2_val[i] +sail(): | + { + let rm_3b = fcsr.FRM(); + let start_element = get_start_element(); + let end_element = get_end_element(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); /* max(VLMAX,VLEN/SEW)) */ + let real_num_elem = if LMUL_pow >= 0 then num_elem else num_elem / (0 - LMUL_pow); /* VLMAX */ + + if illegal_fp_vd_masked(vd, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + + let tail_ag : agtype = get_vtype_vta(); + foreach (i from 0 to (num_elem - 1)) { + if i < start_element then { + result[i] = vd_val[i] + } else if i > end_element | i >= real_num_elem then { + result[i] = match tail_ag { + UNDISTURBED => vd_val[i], + AGNOSTIC => vd_val[i] /* TODO: configuration support */ } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } else { + /* the merge operates on all body elements */ + result[i] = if vm_val[i] then rs1_val else vs2_val[i] + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmin.vf.yaml b/arch/inst/V/vfmin.vf.yaml index 278929ab0..e6d871cd0 100644 --- a/arch/inst/V/vfmin.vf.yaml +++ b/arch/inst/V/vfmin.vf.yaml @@ -1,85 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmin.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000100-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmin.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000100-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), - VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), - VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), - VF_VMIN => fp_min(vs2_val[i], rs1_val), - VF_VMAX => fp_max(vs2_val[i], rs1_val), - VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), - VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), - VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), - VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], - VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSLIDE1UP => { - if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - VF_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), + VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), + VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), + VF_VMIN => fp_min(vs2_val[i], rs1_val), + VF_VMAX => fp_max(vs2_val[i], rs1_val), + VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), + VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), + VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), + VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], + VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSLIDE1UP => { + if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + VF_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmin.vv.yaml b/arch/inst/V/vfmin.vv.yaml index 687e6d161..abf1b633b 100644 --- a/arch/inst/V/vfmin.vv.yaml +++ b/arch/inst/V/vfmin.vv.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmin.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000100-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmin.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000100-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), - FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), - FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], - FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], - FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), + FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), + FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], + FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], + FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmsac.vf.yaml b/arch/inst/V/vfmsac.vf.yaml index 226d82728..1f43e1cd8 100644 --- a/arch/inst/V/vfmsac.vf.yaml +++ b/arch/inst/V/vfmsac.vf.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmsac.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101110-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmsac.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101110-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmsac.vv.yaml b/arch/inst/V/vfmsac.vv.yaml index ac5d34c07..b4215b02e 100644 --- a/arch/inst/V/vfmsac.vv.yaml +++ b/arch/inst/V/vfmsac.vv.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmsac.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101110-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmsac.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101110-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmsub.vf.yaml b/arch/inst/V/vfmsub.vf.yaml index 4e17f4db7..785099841 100644 --- a/arch/inst/V/vfmsub.vf.yaml +++ b/arch/inst/V/vfmsub.vf.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmsub.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101010-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmsub.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101010-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmsub.vv.yaml b/arch/inst/V/vfmsub.vv.yaml index e78a49eaa..cf3a1fadb 100644 --- a/arch/inst/V/vfmsub.vv.yaml +++ b/arch/inst/V/vfmsub.vv.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmsub.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101010-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmsub.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101010-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmul.vf.yaml b/arch/inst/V/vfmul.vf.yaml index b628af0b2..25c1b668d 100644 --- a/arch/inst/V/vfmul.vf.yaml +++ b/arch/inst/V/vfmul.vf.yaml @@ -1,85 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmul.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100100-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmul.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100100-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), - VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), - VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), - VF_VMIN => fp_min(vs2_val[i], rs1_val), - VF_VMAX => fp_max(vs2_val[i], rs1_val), - VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), - VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), - VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), - VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], - VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSLIDE1UP => { - if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - VF_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), + VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), + VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), + VF_VMIN => fp_min(vs2_val[i], rs1_val), + VF_VMAX => fp_max(vs2_val[i], rs1_val), + VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), + VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), + VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), + VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], + VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSLIDE1UP => { + if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + VF_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmul.vv.yaml b/arch/inst/V/vfmul.vv.yaml index fe34f5b4d..b569def98 100644 --- a/arch/inst/V/vfmul.vv.yaml +++ b/arch/inst/V/vfmul.vv.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmul.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100100-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmul.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100100-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), - FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), - FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], - FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], - FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), + FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), + FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], + FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], + FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmv.f.s.yaml b/arch/inst/V/vfmv.f.s.yaml index 3071666c7..2a0a9885c 100644 --- a/arch/inst/V/vfmv.f.s.yaml +++ b/arch/inst/V/vfmv.f.s.yaml @@ -1,51 +1,52 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmv.f.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, xd - encoding: - match: 0100001-----00000001-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmv.f.s +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, xd +encoding: + match: 0100001-----00000001-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let num_elem = get_num_elem(0, SEW); - - if illegal_fp_vd_unmasked(SEW, rm_3b) | SEW > sizeof(flen) - then { handle_illegal(); return RETIRE_FAIL }; - assert(num_elem > 0 & SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, 0, vs2); - match 'm { - 16 => F_H(rd) = vs2_val[0], - 32 => F_S(rd) = vs2_val[0], - 64 => F_D(rd) = vs2_val[0] - }; - vstart = zeros(); - - RETIRE_SUCCESS - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let num_elem = get_num_elem(0, SEW); - \ No newline at end of file + if illegal_fp_vd_unmasked(SEW, rm_3b) | SEW > sizeof(flen) + then { handle_illegal(); return RETIRE_FAIL }; + assert(num_elem > 0 & SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, 0, vs2); + match 'm { + 16 => F_H(rd) = vs2_val[0], + 32 => F_S(rd) = vs2_val[0], + 64 => F_D(rd) = vs2_val[0] + }; + vstart = zeros(); + + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmv.s.f.yaml b/arch/inst/V/vfmv.s.f.yaml index 277fb79df..04ffb840c 100644 --- a/arch/inst/V/vfmv.s.f.yaml +++ b/arch/inst/V/vfmv.s.f.yaml @@ -1,64 +1,65 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmv.s.f: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 010000100000-----101-----1010111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmv.s.f +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 010000100000-----101-----1010111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let num_elem = get_num_elem(0, SEW); - - if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(num_elem > 0 & SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, 0, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, 0, vd_val, vm_val); - - /* one body element */ - if mask[0] then result[0] = rs1_val; - - /* others treated as tail elements */ - let tail_ag : agtype = get_vtype_vta(); - foreach (i from 1 to (num_elem - 1)) { - result[i] = match tail_ag { - UNDISTURBED => vd_val[i], - AGNOSTIC => vd_val[i] /* TODO: configuration support */ - } - }; - - write_vreg(num_elem, SEW, 0, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let num_elem = get_num_elem(0, SEW); - \ No newline at end of file + if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(num_elem > 0 & SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, 0, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, 0, vd_val, vm_val); + + /* one body element */ + if mask[0] then result[0] = rs1_val; + + /* others treated as tail elements */ + let tail_ag : agtype = get_vtype_vta(); + foreach (i from 1 to (num_elem - 1)) { + result[i] = match tail_ag { + UNDISTURBED => vd_val[i], + AGNOSTIC => vd_val[i] /* TODO: configuration support */ + } + }; + + write_vreg(num_elem, SEW, 0, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfmv.v.f.yaml b/arch/inst/V/vfmv.v.f.yaml index 30d48a07d..51b4404e3 100644 --- a/arch/inst/V/vfmv.v.f.yaml +++ b/arch/inst/V/vfmv.v.f.yaml @@ -1,57 +1,58 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfmv.v.f: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 010111100000-----101-----1010111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfmv.v.f +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 010111100000-----101-----1010111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then result[i] = rs1_val - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then result[i] = rs1_val + }; + + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfncvt.f.f.w.yaml b/arch/inst/V/vfncvt.f.f.w.yaml index 472d85bcc..c193f5a80 100644 --- a/arch/inst/V/vfncvt.f.f.w.yaml +++ b/arch/inst/V/vfncvt.f.f.w.yaml @@ -1,138 +1,139 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfncvt.f.f.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------10100001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfncvt.f.f.w +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------10100001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfnunary0 { - FNV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_ROD_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(0b110, vs2_val[i]), - 32 => riscv_f64ToF32(0b110, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(0b001, vs2_val[i]), - 16 => riscv_f32ToUi16(0b001, vs2_val[i]), - 32 => riscv_f64ToUi32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(0b001, vs2_val[i]), - 16 => riscv_f32ToI16(0b001, vs2_val[i]), - 32 => riscv_f64ToI32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfnunary0 { + FNV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_ROD_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(0b110, vs2_val[i]), + 32 => riscv_f64ToF32(0b110, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(0b001, vs2_val[i]), + 16 => riscv_f32ToUi16(0b001, vs2_val[i]), + 32 => riscv_f64ToUi32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(0b001, vs2_val[i]), + 16 => riscv_f32ToI16(0b001, vs2_val[i]), + 32 => riscv_f64ToI32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfncvt.f.x.w.yaml b/arch/inst/V/vfncvt.f.x.w.yaml index 3402fdca6..5c6c764e8 100644 --- a/arch/inst/V/vfncvt.f.x.w.yaml +++ b/arch/inst/V/vfncvt.f.x.w.yaml @@ -1,138 +1,139 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfncvt.f.x.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------10011001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfncvt.f.x.w +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------10011001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfnunary0 { - FNV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_ROD_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(0b110, vs2_val[i]), - 32 => riscv_f64ToF32(0b110, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(0b001, vs2_val[i]), - 16 => riscv_f32ToUi16(0b001, vs2_val[i]), - 32 => riscv_f64ToUi32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(0b001, vs2_val[i]), - 16 => riscv_f32ToI16(0b001, vs2_val[i]), - 32 => riscv_f64ToI32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfnunary0 { + FNV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_ROD_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(0b110, vs2_val[i]), + 32 => riscv_f64ToF32(0b110, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(0b001, vs2_val[i]), + 16 => riscv_f32ToUi16(0b001, vs2_val[i]), + 32 => riscv_f64ToUi32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(0b001, vs2_val[i]), + 16 => riscv_f32ToI16(0b001, vs2_val[i]), + 32 => riscv_f64ToI32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfncvt.f.xu.w.yaml b/arch/inst/V/vfncvt.f.xu.w.yaml index e8abd6fce..37df32206 100644 --- a/arch/inst/V/vfncvt.f.xu.w.yaml +++ b/arch/inst/V/vfncvt.f.xu.w.yaml @@ -1,138 +1,139 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfncvt.f.xu.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------10010001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfncvt.f.xu.w +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------10010001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfnunary0 { - FNV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_ROD_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(0b110, vs2_val[i]), - 32 => riscv_f64ToF32(0b110, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(0b001, vs2_val[i]), - 16 => riscv_f32ToUi16(0b001, vs2_val[i]), - 32 => riscv_f64ToUi32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(0b001, vs2_val[i]), - 16 => riscv_f32ToI16(0b001, vs2_val[i]), - 32 => riscv_f64ToI32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfnunary0 { + FNV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_ROD_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(0b110, vs2_val[i]), + 32 => riscv_f64ToF32(0b110, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(0b001, vs2_val[i]), + 16 => riscv_f32ToUi16(0b001, vs2_val[i]), + 32 => riscv_f64ToUi32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(0b001, vs2_val[i]), + 16 => riscv_f32ToI16(0b001, vs2_val[i]), + 32 => riscv_f64ToI32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfncvt.rod.f.f.w.yaml b/arch/inst/V/vfncvt.rod.f.f.w.yaml index 9870cdbfb..574c2c172 100644 --- a/arch/inst/V/vfncvt.rod.f.f.w.yaml +++ b/arch/inst/V/vfncvt.rod.f.f.w.yaml @@ -1,138 +1,139 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfncvt.rod.f.f.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------10101001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfncvt.rod.f.f.w +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------10101001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfnunary0 { - FNV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_ROD_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(0b110, vs2_val[i]), - 32 => riscv_f64ToF32(0b110, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(0b001, vs2_val[i]), - 16 => riscv_f32ToUi16(0b001, vs2_val[i]), - 32 => riscv_f64ToUi32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(0b001, vs2_val[i]), - 16 => riscv_f32ToI16(0b001, vs2_val[i]), - 32 => riscv_f64ToI32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfnunary0 { + FNV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_ROD_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(0b110, vs2_val[i]), + 32 => riscv_f64ToF32(0b110, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(0b001, vs2_val[i]), + 16 => riscv_f32ToUi16(0b001, vs2_val[i]), + 32 => riscv_f64ToUi32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(0b001, vs2_val[i]), + 16 => riscv_f32ToI16(0b001, vs2_val[i]), + 32 => riscv_f64ToI32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfncvt.rtz.x.f.w.yaml b/arch/inst/V/vfncvt.rtz.x.f.w.yaml index 4ceb29ba6..d7ea4bec1 100644 --- a/arch/inst/V/vfncvt.rtz.x.f.w.yaml +++ b/arch/inst/V/vfncvt.rtz.x.f.w.yaml @@ -1,138 +1,139 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfncvt.rtz.x.f.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------10111001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfncvt.rtz.x.f.w +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------10111001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfnunary0 { - FNV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_ROD_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(0b110, vs2_val[i]), - 32 => riscv_f64ToF32(0b110, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(0b001, vs2_val[i]), - 16 => riscv_f32ToUi16(0b001, vs2_val[i]), - 32 => riscv_f64ToUi32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(0b001, vs2_val[i]), - 16 => riscv_f32ToI16(0b001, vs2_val[i]), - 32 => riscv_f64ToI32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfnunary0 { + FNV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_ROD_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(0b110, vs2_val[i]), + 32 => riscv_f64ToF32(0b110, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(0b001, vs2_val[i]), + 16 => riscv_f32ToUi16(0b001, vs2_val[i]), + 32 => riscv_f64ToUi32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(0b001, vs2_val[i]), + 16 => riscv_f32ToI16(0b001, vs2_val[i]), + 32 => riscv_f64ToI32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfncvt.rtz.xu.f.w.yaml b/arch/inst/V/vfncvt.rtz.xu.f.w.yaml index a25996ab1..2bea9fff1 100644 --- a/arch/inst/V/vfncvt.rtz.xu.f.w.yaml +++ b/arch/inst/V/vfncvt.rtz.xu.f.w.yaml @@ -1,138 +1,139 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfncvt.rtz.xu.f.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------10110001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfncvt.rtz.xu.f.w +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------10110001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfnunary0 { - FNV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_ROD_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(0b110, vs2_val[i]), - 32 => riscv_f64ToF32(0b110, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(0b001, vs2_val[i]), - 16 => riscv_f32ToUi16(0b001, vs2_val[i]), - 32 => riscv_f64ToUi32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(0b001, vs2_val[i]), - 16 => riscv_f32ToI16(0b001, vs2_val[i]), - 32 => riscv_f64ToI32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfnunary0 { + FNV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_ROD_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(0b110, vs2_val[i]), + 32 => riscv_f64ToF32(0b110, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(0b001, vs2_val[i]), + 16 => riscv_f32ToUi16(0b001, vs2_val[i]), + 32 => riscv_f64ToUi32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(0b001, vs2_val[i]), + 16 => riscv_f32ToI16(0b001, vs2_val[i]), + 32 => riscv_f64ToI32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfncvt.x.f.w.yaml b/arch/inst/V/vfncvt.x.f.w.yaml index b68d0807c..f20b998b5 100644 --- a/arch/inst/V/vfncvt.x.f.w.yaml +++ b/arch/inst/V/vfncvt.x.f.w.yaml @@ -1,138 +1,139 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfncvt.x.f.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------10001001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfncvt.x.f.w +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------10001001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfnunary0 { - FNV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_ROD_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(0b110, vs2_val[i]), - 32 => riscv_f64ToF32(0b110, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(0b001, vs2_val[i]), - 16 => riscv_f32ToUi16(0b001, vs2_val[i]), - 32 => riscv_f64ToUi32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(0b001, vs2_val[i]), - 16 => riscv_f32ToI16(0b001, vs2_val[i]), - 32 => riscv_f64ToI32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfnunary0 { + FNV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_ROD_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(0b110, vs2_val[i]), + 32 => riscv_f64ToF32(0b110, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(0b001, vs2_val[i]), + 16 => riscv_f32ToUi16(0b001, vs2_val[i]), + 32 => riscv_f64ToUi32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(0b001, vs2_val[i]), + 16 => riscv_f32ToI16(0b001, vs2_val[i]), + 32 => riscv_f64ToI32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfncvt.xu.f.w.yaml b/arch/inst/V/vfncvt.xu.f.w.yaml index 17851a428..6878beea4 100644 --- a/arch/inst/V/vfncvt.xu.f.w.yaml +++ b/arch/inst/V/vfncvt.xu.f.w.yaml @@ -1,138 +1,139 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfncvt.xu.f.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------10000001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfncvt.xu.f.w +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------10000001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfnunary0 { - FNV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), - 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), - 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_ROD_F_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f32ToF16(0b110, vs2_val[i]), - 32 => riscv_f64ToF32(0b110, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToUi8(0b001, vs2_val[i]), - 16 => riscv_f32ToUi16(0b001, vs2_val[i]), - 32 => riscv_f64ToUi32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FNV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 8 => riscv_f16ToI8(0b001, vs2_val[i]), - 16 => riscv_f32ToI16(0b001, vs2_val[i]), - 32 => riscv_f64ToI32(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfnunary0 { + FNV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToUi16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToUi32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(rm_3b, vs2_val[i]), + 16 => riscv_f32ToI16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToI32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_ui32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_ui64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_i32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_i64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(rm_3b, vs2_val[i]), + 32 => riscv_f64ToF32(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_ROD_F_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f32ToF16(0b110, vs2_val[i]), + 32 => riscv_f64ToF32(0b110, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToUi8(0b001, vs2_val[i]), + 16 => riscv_f32ToUi16(0b001, vs2_val[i]), + 32 => riscv_f64ToUi32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FNV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 8 => riscv_f16ToI8(0b001, vs2_val[i]), + 16 => riscv_f32ToI16(0b001, vs2_val[i]), + 32 => riscv_f64ToI32(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfnmacc.vf.yaml b/arch/inst/V/vfnmacc.vf.yaml index 2a95d27f3..56e6ca4f2 100644 --- a/arch/inst/V/vfnmacc.vf.yaml +++ b/arch/inst/V/vfnmacc.vf.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfnmacc.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101101-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfnmacc.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101101-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfnmacc.vv.yaml b/arch/inst/V/vfnmacc.vv.yaml index 6c1b7c59d..e33d710ef 100644 --- a/arch/inst/V/vfnmacc.vv.yaml +++ b/arch/inst/V/vfnmacc.vv.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfnmacc.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101101-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfnmacc.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101101-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfnmadd.vf.yaml b/arch/inst/V/vfnmadd.vf.yaml index 98ef7293c..4f55a64ea 100644 --- a/arch/inst/V/vfnmadd.vf.yaml +++ b/arch/inst/V/vfnmadd.vf.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfnmadd.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101001-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfnmadd.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101001-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfnmadd.vv.yaml b/arch/inst/V/vfnmadd.vv.yaml index d65226d9d..adcdaa931 100644 --- a/arch/inst/V/vfnmadd.vv.yaml +++ b/arch/inst/V/vfnmadd.vv.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfnmadd.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101001-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfnmadd.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101001-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfnmsac.vf.yaml b/arch/inst/V/vfnmsac.vf.yaml index 8f1f772f7..bbfd36edd 100644 --- a/arch/inst/V/vfnmsac.vf.yaml +++ b/arch/inst/V/vfnmsac.vf.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfnmsac.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101111-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfnmsac.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101111-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfnmsac.vv.yaml b/arch/inst/V/vfnmsac.vv.yaml index 34b3c427e..ebece29cb 100644 --- a/arch/inst/V/vfnmsac.vv.yaml +++ b/arch/inst/V/vfnmsac.vv.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfnmsac.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101111-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfnmsac.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101111-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfnmsub.vf.yaml b/arch/inst/V/vfnmsub.vf.yaml index 1e0eba053..2af355ef8 100644 --- a/arch/inst/V/vfnmsub.vf.yaml +++ b/arch/inst/V/vfnmsub.vf.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfnmsub.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101011-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfnmsub.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101011-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), - VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), - VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VMACC => fp_muladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMACC => fp_nmulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMSAC => fp_mulsub(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VNMSAC => fp_nmuladd(rm_3b, rs1_val, vs2_val[i], vd_val[i]), + VF_VMADD => fp_muladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMADD => fp_nmulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VMSUB => fp_mulsub(rm_3b, rs1_val, vd_val[i], vs2_val[i]), + VF_VNMSUB => fp_nmuladd(rm_3b, rs1_val, vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfnmsub.vv.yaml b/arch/inst/V/vfnmsub.vv.yaml index ef0750019..3272bacc4 100644 --- a/arch/inst/V/vfnmsub.vv.yaml +++ b/arch/inst/V/vfnmsub.vv.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfnmsub.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101011-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfnmsub.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101011-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), - FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), - FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VMACC => fp_muladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMACC => fp_nmulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMSAC => fp_mulsub(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VNMSAC => fp_nmuladd(rm_3b, vs1_val[i], vs2_val[i], vd_val[i]), + FVV_VMADD => fp_muladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMADD => fp_nmulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VMSUB => fp_mulsub(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]), + FVV_VNMSUB => fp_nmuladd(rm_3b, vs1_val[i], vd_val[i], vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfrdiv.vf.yaml b/arch/inst/V/vfrdiv.vf.yaml index a4c21768f..2beaafcb7 100644 --- a/arch/inst/V/vfrdiv.vf.yaml +++ b/arch/inst/V/vfrdiv.vf.yaml @@ -1,85 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfrdiv.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100001-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfrdiv.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100001-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), - VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), - VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), - VF_VMIN => fp_min(vs2_val[i], rs1_val), - VF_VMAX => fp_max(vs2_val[i], rs1_val), - VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), - VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), - VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), - VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], - VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSLIDE1UP => { - if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - VF_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), + VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), + VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), + VF_VMIN => fp_min(vs2_val[i], rs1_val), + VF_VMAX => fp_max(vs2_val[i], rs1_val), + VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), + VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), + VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), + VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], + VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSLIDE1UP => { + if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + VF_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfrec7.v.yaml b/arch/inst/V/vfrec7.v.yaml index bd0f9ba98..e17cc89b4 100644 --- a/arch/inst/V/vfrec7.v.yaml +++ b/arch/inst/V/vfrec7.v.yaml @@ -1,90 +1,91 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfrec7.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010011------00101001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfrec7.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010011------00101001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfunary1 { - FVV_VSQRT => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16Sqrt(rm_3b, vs2_val[i]), - 32 => riscv_f32Sqrt(rm_3b, vs2_val[i]), - 64 => riscv_f64Sqrt(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FVV_VRSQRT7 => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16Rsqrte7(rm_3b, vs2_val[i]), - 32 => riscv_f32Rsqrte7(rm_3b, vs2_val[i]), - 64 => riscv_f64Rsqrte7(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FVV_VREC7 => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16Recip7(rm_3b, vs2_val[i]), - 32 => riscv_f32Recip7(rm_3b, vs2_val[i]), - 64 => riscv_f64Recip7(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FVV_VCLASS => fp_class(vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfunary1 { + FVV_VSQRT => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16Sqrt(rm_3b, vs2_val[i]), + 32 => riscv_f32Sqrt(rm_3b, vs2_val[i]), + 64 => riscv_f64Sqrt(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FVV_VRSQRT7 => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16Rsqrte7(rm_3b, vs2_val[i]), + 32 => riscv_f32Rsqrte7(rm_3b, vs2_val[i]), + 64 => riscv_f64Rsqrte7(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FVV_VREC7 => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16Recip7(rm_3b, vs2_val[i]), + 32 => riscv_f32Recip7(rm_3b, vs2_val[i]), + 64 => riscv_f64Recip7(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FVV_VCLASS => fp_class(vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfredmax.vs.yaml b/arch/inst/V/vfredmax.vs.yaml index 43bb68772..9162d9cfd 100644 --- a/arch/inst/V/vfredmax.vs.yaml +++ b/arch/inst/V/vfredmax.vs.yaml @@ -1,43 +1,44 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfredmax.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000111-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfredmax.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000111-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - - if funct6 == FVV_VFWREDOSUM | funct6 == FVV_VFWREDUSUM then - process_rfvv_widen(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) - else - process_rfvv_single(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if funct6 == FVV_VFWREDOSUM | funct6 == FVV_VFWREDUSUM then + process_rfvv_widen(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) + else + process_rfvv_single(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) + } + diff --git a/arch/inst/V/vfredmin.vs.yaml b/arch/inst/V/vfredmin.vs.yaml index 1e9a6b532..2421e017f 100644 --- a/arch/inst/V/vfredmin.vs.yaml +++ b/arch/inst/V/vfredmin.vs.yaml @@ -1,43 +1,44 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfredmin.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000101-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfredmin.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000101-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - - if funct6 == FVV_VFWREDOSUM | funct6 == FVV_VFWREDUSUM then - process_rfvv_widen(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) - else - process_rfvv_single(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if funct6 == FVV_VFWREDOSUM | funct6 == FVV_VFWREDUSUM then + process_rfvv_widen(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) + else + process_rfvv_single(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) + } + diff --git a/arch/inst/V/vfredosum.vs.yaml b/arch/inst/V/vfredosum.vs.yaml index 8f50e26ba..e343e1628 100644 --- a/arch/inst/V/vfredosum.vs.yaml +++ b/arch/inst/V/vfredosum.vs.yaml @@ -1,43 +1,44 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfredosum.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000011-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfredosum.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000011-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - - if funct6 == FVV_VFWREDOSUM | funct6 == FVV_VFWREDUSUM then - process_rfvv_widen(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) - else - process_rfvv_single(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if funct6 == FVV_VFWREDOSUM | funct6 == FVV_VFWREDUSUM then + process_rfvv_widen(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) + else + process_rfvv_single(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) + } + diff --git a/arch/inst/V/vfredusum.vs.yaml b/arch/inst/V/vfredusum.vs.yaml index 4ed77f985..2b6938156 100644 --- a/arch/inst/V/vfredusum.vs.yaml +++ b/arch/inst/V/vfredusum.vs.yaml @@ -1,43 +1,44 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfredusum.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000001-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfredusum.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000001-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - - if funct6 == FVV_VFWREDOSUM | funct6 == FVV_VFWREDUSUM then - process_rfvv_widen(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) - else - process_rfvv_single(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if funct6 == FVV_VFWREDOSUM | funct6 == FVV_VFWREDUSUM then + process_rfvv_widen(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) + else + process_rfvv_single(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) + } + diff --git a/arch/inst/V/vfrsqrt7.v.yaml b/arch/inst/V/vfrsqrt7.v.yaml index 6d2e9cbcb..2276abd0c 100644 --- a/arch/inst/V/vfrsqrt7.v.yaml +++ b/arch/inst/V/vfrsqrt7.v.yaml @@ -1,90 +1,91 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfrsqrt7.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010011------00100001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfrsqrt7.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010011------00100001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfunary1 { - FVV_VSQRT => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16Sqrt(rm_3b, vs2_val[i]), - 32 => riscv_f32Sqrt(rm_3b, vs2_val[i]), - 64 => riscv_f64Sqrt(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FVV_VRSQRT7 => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16Rsqrte7(rm_3b, vs2_val[i]), - 32 => riscv_f32Rsqrte7(rm_3b, vs2_val[i]), - 64 => riscv_f64Rsqrte7(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FVV_VREC7 => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16Recip7(rm_3b, vs2_val[i]), - 32 => riscv_f32Recip7(rm_3b, vs2_val[i]), - 64 => riscv_f64Recip7(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FVV_VCLASS => fp_class(vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfunary1 { + FVV_VSQRT => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16Sqrt(rm_3b, vs2_val[i]), + 32 => riscv_f32Sqrt(rm_3b, vs2_val[i]), + 64 => riscv_f64Sqrt(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FVV_VRSQRT7 => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16Rsqrte7(rm_3b, vs2_val[i]), + 32 => riscv_f32Rsqrte7(rm_3b, vs2_val[i]), + 64 => riscv_f64Rsqrte7(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FVV_VREC7 => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16Recip7(rm_3b, vs2_val[i]), + 32 => riscv_f32Recip7(rm_3b, vs2_val[i]), + 64 => riscv_f64Recip7(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FVV_VCLASS => fp_class(vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfrsub.vf.yaml b/arch/inst/V/vfrsub.vf.yaml index 03b57ee68..7175d5ea1 100644 --- a/arch/inst/V/vfrsub.vf.yaml +++ b/arch/inst/V/vfrsub.vf.yaml @@ -1,85 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfrsub.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100111-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfrsub.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100111-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), - VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), - VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), - VF_VMIN => fp_min(vs2_val[i], rs1_val), - VF_VMAX => fp_max(vs2_val[i], rs1_val), - VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), - VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), - VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), - VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], - VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSLIDE1UP => { - if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - VF_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), + VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), + VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), + VF_VMIN => fp_min(vs2_val[i], rs1_val), + VF_VMAX => fp_max(vs2_val[i], rs1_val), + VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), + VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), + VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), + VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], + VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSLIDE1UP => { + if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + VF_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfsgnj.vf.yaml b/arch/inst/V/vfsgnj.vf.yaml index aa412fa06..46fbfb495 100644 --- a/arch/inst/V/vfsgnj.vf.yaml +++ b/arch/inst/V/vfsgnj.vf.yaml @@ -1,85 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfsgnj.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001000-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfsgnj.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001000-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), - VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), - VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), - VF_VMIN => fp_min(vs2_val[i], rs1_val), - VF_VMAX => fp_max(vs2_val[i], rs1_val), - VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), - VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), - VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), - VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], - VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSLIDE1UP => { - if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - VF_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), + VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), + VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), + VF_VMIN => fp_min(vs2_val[i], rs1_val), + VF_VMAX => fp_max(vs2_val[i], rs1_val), + VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), + VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), + VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), + VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], + VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSLIDE1UP => { + if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + VF_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfsgnj.vv.yaml b/arch/inst/V/vfsgnj.vv.yaml index 3cb6886fa..f256057d4 100644 --- a/arch/inst/V/vfsgnj.vv.yaml +++ b/arch/inst/V/vfsgnj.vv.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfsgnj.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 001000-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfsgnj.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 001000-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), - FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), - FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], - FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], - FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), + FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), + FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], + FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], + FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfsgnjn.vf.yaml b/arch/inst/V/vfsgnjn.vf.yaml index 1f71c02c5..6de073a93 100644 --- a/arch/inst/V/vfsgnjn.vf.yaml +++ b/arch/inst/V/vfsgnjn.vf.yaml @@ -1,85 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfsgnjn.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001001-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfsgnjn.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001001-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), - VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), - VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), - VF_VMIN => fp_min(vs2_val[i], rs1_val), - VF_VMAX => fp_max(vs2_val[i], rs1_val), - VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), - VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), - VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), - VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], - VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSLIDE1UP => { - if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - VF_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), + VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), + VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), + VF_VMIN => fp_min(vs2_val[i], rs1_val), + VF_VMAX => fp_max(vs2_val[i], rs1_val), + VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), + VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), + VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), + VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], + VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSLIDE1UP => { + if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + VF_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfsgnjn.vv.yaml b/arch/inst/V/vfsgnjn.vv.yaml index cecb07233..3e4d499fa 100644 --- a/arch/inst/V/vfsgnjn.vv.yaml +++ b/arch/inst/V/vfsgnjn.vv.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfsgnjn.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 001001-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfsgnjn.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 001001-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), - FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), - FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], - FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], - FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), + FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), + FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], + FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], + FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfsgnjx.vf.yaml b/arch/inst/V/vfsgnjx.vf.yaml index 7cdab9785..eb4597bdc 100644 --- a/arch/inst/V/vfsgnjx.vf.yaml +++ b/arch/inst/V/vfsgnjx.vf.yaml @@ -1,85 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfsgnjx.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001010-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfsgnjx.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001010-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), - VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), - VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), - VF_VMIN => fp_min(vs2_val[i], rs1_val), - VF_VMAX => fp_max(vs2_val[i], rs1_val), - VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), - VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), - VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), - VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], - VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSLIDE1UP => { - if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - VF_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), + VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), + VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), + VF_VMIN => fp_min(vs2_val[i], rs1_val), + VF_VMAX => fp_max(vs2_val[i], rs1_val), + VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), + VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), + VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), + VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], + VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSLIDE1UP => { + if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + VF_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfsgnjx.vv.yaml b/arch/inst/V/vfsgnjx.vv.yaml index 041fd0126..3b16d69b6 100644 --- a/arch/inst/V/vfsgnjx.vv.yaml +++ b/arch/inst/V/vfsgnjx.vv.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfsgnjx.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 001010-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfsgnjx.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 001010-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), - FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), - FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], - FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], - FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), + FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), + FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], + FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], + FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfslide1down.vf.yaml b/arch/inst/V/vfslide1down.vf.yaml index 6f54214e8..525f9fb53 100644 --- a/arch/inst/V/vfslide1down.vf.yaml +++ b/arch/inst/V/vfslide1down.vf.yaml @@ -1,85 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfslide1down.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001111-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfslide1down.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001111-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), - VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), - VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), - VF_VMIN => fp_min(vs2_val[i], rs1_val), - VF_VMAX => fp_max(vs2_val[i], rs1_val), - VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), - VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), - VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), - VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], - VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSLIDE1UP => { - if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - VF_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), + VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), + VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), + VF_VMIN => fp_min(vs2_val[i], rs1_val), + VF_VMAX => fp_max(vs2_val[i], rs1_val), + VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), + VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), + VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), + VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], + VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSLIDE1UP => { + if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + VF_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfslide1up.vf.yaml b/arch/inst/V/vfslide1up.vf.yaml index 991c6f8b0..a76a2c433 100644 --- a/arch/inst/V/vfslide1up.vf.yaml +++ b/arch/inst/V/vfslide1up.vf.yaml @@ -1,85 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfslide1up.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001110-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfslide1up.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001110-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), - VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), - VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), - VF_VMIN => fp_min(vs2_val[i], rs1_val), - VF_VMAX => fp_max(vs2_val[i], rs1_val), - VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), - VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), - VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), - VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], - VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSLIDE1UP => { - if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - VF_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), + VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), + VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), + VF_VMIN => fp_min(vs2_val[i], rs1_val), + VF_VMAX => fp_max(vs2_val[i], rs1_val), + VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), + VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), + VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), + VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], + VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSLIDE1UP => { + if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + VF_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfsqrt.v.yaml b/arch/inst/V/vfsqrt.v.yaml index b99ea4ac0..f3ddf5924 100644 --- a/arch/inst/V/vfsqrt.v.yaml +++ b/arch/inst/V/vfsqrt.v.yaml @@ -1,90 +1,91 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfsqrt.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010011------00000001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfsqrt.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010011------00000001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfunary1 { - FVV_VSQRT => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16Sqrt(rm_3b, vs2_val[i]), - 32 => riscv_f32Sqrt(rm_3b, vs2_val[i]), - 64 => riscv_f64Sqrt(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FVV_VRSQRT7 => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16Rsqrte7(rm_3b, vs2_val[i]), - 32 => riscv_f32Rsqrte7(rm_3b, vs2_val[i]), - 64 => riscv_f64Rsqrte7(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FVV_VREC7 => { - let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { - 16 => riscv_f16Recip7(rm_3b, vs2_val[i]), - 32 => riscv_f32Recip7(rm_3b, vs2_val[i]), - 64 => riscv_f64Recip7(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FVV_VCLASS => fp_class(vs2_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfunary1 { + FVV_VSQRT => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16Sqrt(rm_3b, vs2_val[i]), + 32 => riscv_f32Sqrt(rm_3b, vs2_val[i]), + 64 => riscv_f64Sqrt(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FVV_VRSQRT7 => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16Rsqrte7(rm_3b, vs2_val[i]), + 32 => riscv_f32Rsqrte7(rm_3b, vs2_val[i]), + 64 => riscv_f64Rsqrte7(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FVV_VREC7 => { + let (fflags, elem) : (bits_fflags, bits('m)) = match 'm { + 16 => riscv_f16Recip7(rm_3b, vs2_val[i]), + 32 => riscv_f32Recip7(rm_3b, vs2_val[i]), + 64 => riscv_f64Recip7(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FVV_VCLASS => fp_class(vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfsub.vf.yaml b/arch/inst/V/vfsub.vf.yaml index 834f59c41..d2ebfd447 100644 --- a/arch/inst/V/vfsub.vf.yaml +++ b/arch/inst/V/vfsub.vf.yaml @@ -1,85 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfsub.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000010-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfsub.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000010-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), - VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), - VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), - VF_VMIN => fp_min(vs2_val[i], rs1_val), - VF_VMAX => fp_max(vs2_val[i], rs1_val), - VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), - VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), - VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), - VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], - VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], - VF_VSLIDE1UP => { - if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - VF_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VF_VADD => fp_add(rm_3b, vs2_val[i], rs1_val), + VF_VSUB => fp_sub(rm_3b, vs2_val[i], rs1_val), + VF_VRSUB => fp_sub(rm_3b, rs1_val, vs2_val[i]), + VF_VMIN => fp_min(vs2_val[i], rs1_val), + VF_VMAX => fp_max(vs2_val[i], rs1_val), + VF_VMUL => fp_mul(rm_3b, vs2_val[i], rs1_val), + VF_VDIV => fp_div(rm_3b, vs2_val[i], rs1_val), + VF_VRDIV => fp_div(rm_3b, rs1_val, vs2_val[i]), + VF_VSGNJ => [rs1_val['m - 1]] @ vs2_val[i][('m - 2)..0], + VF_VSGNJN => (0b1 ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSGNJX => ([vs2_val[i]['m - 1]] ^ [rs1_val['m - 1]]) @ vs2_val[i][('m - 2)..0], + VF_VSLIDE1UP => { + if vs2 == vd then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + VF_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfsub.vv.yaml b/arch/inst/V/vfsub.vv.yaml index f9ac5b4a6..6a91b4549 100644 --- a/arch/inst/V/vfsub.vv.yaml +++ b/arch/inst/V/vfsub.vv.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfsub.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000010-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfsub.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000010-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), - FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), - FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), - FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], - FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], - FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_fp_normal(vd, vm, SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FVV_VADD => fp_add(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSUB => fp_sub(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VMIN => fp_min(vs2_val[i], vs1_val[i]), + FVV_VMAX => fp_max(vs2_val[i], vs1_val[i]), + FVV_VMUL => fp_mul(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VDIV => fp_div(rm_3b, vs2_val[i], vs1_val[i]), + FVV_VSGNJ => [vs1_val[i]['m - 1]] @ vs2_val[i][('m - 2)..0], + FVV_VSGNJN => (0b1 ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0], + FVV_VSGNJX => ([vs2_val[i]['m - 1]] ^ [vs1_val[i]['m - 1]]) @ vs2_val[i][('m - 2)..0] } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwadd.vf.yaml b/arch/inst/V/vfwadd.vf.yaml index 79ad6a9ba..26979ae97 100644 --- a/arch/inst/V/vfwadd.vf.yaml +++ b/arch/inst/V/vfwadd.vf.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwadd.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 110000-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwadd.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 110000-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVF_VADD => fp_add(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)), - FWVF_VSUB => fp_sub(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)), - FWVF_VMUL => fp_mul(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVF_VADD => fp_add(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)), + FWVF_VSUB => fp_sub(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)), + FWVF_VMUL => fp_mul(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwadd.vv.yaml b/arch/inst/V/vfwadd.vv.yaml index f50ec3e4a..2a9d94d13 100644 --- a/arch/inst/V/vfwadd.vv.yaml +++ b/arch/inst/V/vfwadd.vv.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwadd.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110000-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwadd.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110000-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVV_VADD => fp_add(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])), - FWVV_VSUB => fp_sub(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])), - FWVV_VMUL => fp_mul(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVV_VADD => fp_add(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])), + FWVV_VSUB => fp_sub(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])), + FWVV_VMUL => fp_mul(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwadd.wf.yaml b/arch/inst/V/vfwadd.wf.yaml index 78d5d9969..984920924 100644 --- a/arch/inst/V/vfwadd.wf.yaml +++ b/arch/inst/V/vfwadd.wf.yaml @@ -1,71 +1,72 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwadd.wf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 110100-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwadd.wf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 110100-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWF_VADD => fp_add(rm_3b, vs2_val[i], fp_widen(rs1_val)), - FWF_VSUB => fp_sub(rm_3b, vs2_val[i], fp_widen(rs1_val)) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWF_VADD => fp_add(rm_3b, vs2_val[i], fp_widen(rs1_val)), + FWF_VSUB => fp_sub(rm_3b, vs2_val[i], fp_widen(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwadd.wv.yaml b/arch/inst/V/vfwadd.wv.yaml index 22db63d4f..1fd17c23d 100644 --- a/arch/inst/V/vfwadd.wv.yaml +++ b/arch/inst/V/vfwadd.wv.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwadd.wv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110100-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwadd.wv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110100-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWV_VADD => fp_add(rm_3b, vs2_val[i], fp_widen(vs1_val[i])), - FWV_VSUB => fp_sub(rm_3b, vs2_val[i], fp_widen(vs1_val[i])) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWV_VADD => fp_add(rm_3b, vs2_val[i], fp_widen(vs1_val[i])), + FWV_VSUB => fp_sub(rm_3b, vs2_val[i], fp_widen(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwcvt.f.f.v.yaml b/arch/inst/V/vfwcvt.f.f.v.yaml index a277c8de4..487d919fb 100644 --- a/arch/inst/V/vfwcvt.f.f.v.yaml +++ b/arch/inst/V/vfwcvt.f.f.v.yaml @@ -1,130 +1,131 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwcvt.f.f.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------01100001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwcvt.f.f.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------01100001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 8 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfwunary0 { - FWV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), - 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), - 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), - 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), - 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(0b001, vs2_val[i]), - 32 => riscv_f32ToUi64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(0b001, vs2_val[i]), - 32 => riscv_f32ToI64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 8 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfwunary0 { + FWV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), + 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), + 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), + 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), + 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(0b001, vs2_val[i]), + 32 => riscv_f32ToUi64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(0b001, vs2_val[i]), + 32 => riscv_f32ToI64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwcvt.f.x.v.yaml b/arch/inst/V/vfwcvt.f.x.v.yaml index 9390f8050..f6c784e06 100644 --- a/arch/inst/V/vfwcvt.f.x.v.yaml +++ b/arch/inst/V/vfwcvt.f.x.v.yaml @@ -1,130 +1,131 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwcvt.f.x.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------01011001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwcvt.f.x.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------01011001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 8 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfwunary0 { - FWV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), - 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), - 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), - 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), - 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(0b001, vs2_val[i]), - 32 => riscv_f32ToUi64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(0b001, vs2_val[i]), - 32 => riscv_f32ToI64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 8 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfwunary0 { + FWV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), + 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), + 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), + 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), + 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(0b001, vs2_val[i]), + 32 => riscv_f32ToUi64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(0b001, vs2_val[i]), + 32 => riscv_f32ToI64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwcvt.f.xu.v.yaml b/arch/inst/V/vfwcvt.f.xu.v.yaml index 73c7f06be..da71b1a3b 100644 --- a/arch/inst/V/vfwcvt.f.xu.v.yaml +++ b/arch/inst/V/vfwcvt.f.xu.v.yaml @@ -1,130 +1,131 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwcvt.f.xu.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------01010001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwcvt.f.xu.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------01010001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 8 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfwunary0 { - FWV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), - 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), - 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), - 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), - 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(0b001, vs2_val[i]), - 32 => riscv_f32ToUi64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(0b001, vs2_val[i]), - 32 => riscv_f32ToI64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 8 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfwunary0 { + FWV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), + 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), + 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), + 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), + 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(0b001, vs2_val[i]), + 32 => riscv_f32ToUi64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(0b001, vs2_val[i]), + 32 => riscv_f32ToI64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwcvt.rtz.x.f.v.yaml b/arch/inst/V/vfwcvt.rtz.x.f.v.yaml index 5eb9a02e2..751d91c8b 100644 --- a/arch/inst/V/vfwcvt.rtz.x.f.v.yaml +++ b/arch/inst/V/vfwcvt.rtz.x.f.v.yaml @@ -1,130 +1,131 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwcvt.rtz.x.f.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------01111001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwcvt.rtz.x.f.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------01111001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 8 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfwunary0 { - FWV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), - 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), - 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), - 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), - 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(0b001, vs2_val[i]), - 32 => riscv_f32ToUi64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(0b001, vs2_val[i]), - 32 => riscv_f32ToI64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 8 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfwunary0 { + FWV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), + 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), + 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), + 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), + 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(0b001, vs2_val[i]), + 32 => riscv_f32ToUi64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(0b001, vs2_val[i]), + 32 => riscv_f32ToI64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwcvt.rtz.xu.f.v.yaml b/arch/inst/V/vfwcvt.rtz.xu.f.v.yaml index 888ae2401..271c14619 100644 --- a/arch/inst/V/vfwcvt.rtz.xu.f.v.yaml +++ b/arch/inst/V/vfwcvt.rtz.xu.f.v.yaml @@ -1,130 +1,131 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwcvt.rtz.xu.f.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------01110001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwcvt.rtz.xu.f.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------01110001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 8 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfwunary0 { - FWV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), - 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), - 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), - 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), - 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(0b001, vs2_val[i]), - 32 => riscv_f32ToUi64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(0b001, vs2_val[i]), - 32 => riscv_f32ToI64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 8 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfwunary0 { + FWV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), + 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), + 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), + 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), + 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(0b001, vs2_val[i]), + 32 => riscv_f32ToUi64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(0b001, vs2_val[i]), + 32 => riscv_f32ToI64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwcvt.x.f.v.yaml b/arch/inst/V/vfwcvt.x.f.v.yaml index c13cbcbdd..e6d8434a4 100644 --- a/arch/inst/V/vfwcvt.x.f.v.yaml +++ b/arch/inst/V/vfwcvt.x.f.v.yaml @@ -1,130 +1,131 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwcvt.x.f.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------01001001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwcvt.x.f.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------01001001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 8 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfwunary0 { - FWV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), - 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), - 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), - 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), - 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(0b001, vs2_val[i]), - 32 => riscv_f32ToUi64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(0b001, vs2_val[i]), - 32 => riscv_f32ToI64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 8 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfwunary0 { + FWV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), + 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), + 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), + 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), + 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(0b001, vs2_val[i]), + 32 => riscv_f32ToUi64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(0b001, vs2_val[i]), + 32 => riscv_f32ToI64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwcvt.xu.f.v.yaml b/arch/inst/V/vfwcvt.xu.f.v.yaml index 494879e62..fe088fcb2 100644 --- a/arch/inst/V/vfwcvt.xu.f.v.yaml +++ b/arch/inst/V/vfwcvt.xu.f.v.yaml @@ -1,130 +1,131 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwcvt.xu.f.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------01000001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwcvt.xu.f.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------01000001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 8 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match vfwunary0 { - FWV_CVT_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_XU => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), - 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), - 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_X => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), - 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), - 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_F_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), - 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_XU_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToUi32(0b001, vs2_val[i]), - 32 => riscv_f32ToUi64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - }, - FWV_CVT_RTZ_X_F => { - let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { - 8 => { handle_illegal(); return RETIRE_FAIL }, - 16 => riscv_f16ToI32(0b001, vs2_val[i]), - 32 => riscv_f32ToI64(0b001, vs2_val[i]) - }; - accrue_fflags(fflags); - elem - } - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 8 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match vfwunary0 { + FWV_CVT_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToUi64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToI64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_XU => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_ui32ToF16(rm_3b, zero_extend(vs2_val[i])), + 16 => riscv_ui32ToF32(rm_3b, zero_extend(vs2_val[i])), + 32 => riscv_ui32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_X => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => riscv_i32ToF16(rm_3b, sign_extend(vs2_val[i])), + 16 => riscv_i32ToF32(rm_3b, sign_extend(vs2_val[i])), + 32 => riscv_i32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_F_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToF32(rm_3b, vs2_val[i]), + 32 => riscv_f32ToF64(rm_3b, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_XU_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToUi32(0b001, vs2_val[i]), + 32 => riscv_f32ToUi64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + }, + FWV_CVT_RTZ_X_F => { + let (fflags, elem) : (bits_fflags, bits('o)) = match 'm { + 8 => { handle_illegal(); return RETIRE_FAIL }, + 16 => riscv_f16ToI32(0b001, vs2_val[i]), + 32 => riscv_f32ToI64(0b001, vs2_val[i]) + }; + accrue_fflags(fflags); + elem + } } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwmacc.vf.yaml b/arch/inst/V/vfwmacc.vf.yaml index a609c6282..0f015804a 100644 --- a/arch/inst/V/vfwmacc.vf.yaml +++ b/arch/inst/V/vfwmacc.vf.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwmacc.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 111100-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwmacc.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 111100-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVF_VMACC => fp_muladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), - FWVF_VNMACC => fp_nmulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), - FWVF_VMSAC => fp_mulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), - FWVF_VNMSAC => fp_nmuladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVF_VMACC => fp_muladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), + FWVF_VNMACC => fp_nmulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), + FWVF_VMSAC => fp_mulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), + FWVF_VNMSAC => fp_nmuladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwmacc.vv.yaml b/arch/inst/V/vfwmacc.vv.yaml index 4f1dd9eca..0875df457 100644 --- a/arch/inst/V/vfwmacc.vv.yaml +++ b/arch/inst/V/vfwmacc.vv.yaml @@ -1,75 +1,76 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwmacc.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 111100-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwmacc.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 111100-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVV_VMACC => fp_muladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), - FWVV_VNMACC => fp_nmulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), - FWVV_VMSAC => fp_mulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), - FWVV_VNMSAC => fp_nmuladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVV_VMACC => fp_muladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), + FWVV_VNMACC => fp_nmulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), + FWVV_VMSAC => fp_mulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), + FWVV_VNMSAC => fp_nmuladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwmsac.vf.yaml b/arch/inst/V/vfwmsac.vf.yaml index 881af1e82..0c33d367f 100644 --- a/arch/inst/V/vfwmsac.vf.yaml +++ b/arch/inst/V/vfwmsac.vf.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwmsac.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 111110-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwmsac.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 111110-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVF_VMACC => fp_muladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), - FWVF_VNMACC => fp_nmulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), - FWVF_VMSAC => fp_mulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), - FWVF_VNMSAC => fp_nmuladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVF_VMACC => fp_muladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), + FWVF_VNMACC => fp_nmulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), + FWVF_VMSAC => fp_mulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), + FWVF_VNMSAC => fp_nmuladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwmsac.vv.yaml b/arch/inst/V/vfwmsac.vv.yaml index 543e48d56..d2b52d9c8 100644 --- a/arch/inst/V/vfwmsac.vv.yaml +++ b/arch/inst/V/vfwmsac.vv.yaml @@ -1,75 +1,76 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwmsac.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 111110-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwmsac.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 111110-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVV_VMACC => fp_muladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), - FWVV_VNMACC => fp_nmulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), - FWVV_VMSAC => fp_mulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), - FWVV_VNMSAC => fp_nmuladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVV_VMACC => fp_muladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), + FWVV_VNMACC => fp_nmulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), + FWVV_VMSAC => fp_mulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), + FWVV_VNMSAC => fp_nmuladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwmul.vf.yaml b/arch/inst/V/vfwmul.vf.yaml index b60450643..db717c712 100644 --- a/arch/inst/V/vfwmul.vf.yaml +++ b/arch/inst/V/vfwmul.vf.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwmul.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 111000-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwmul.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 111000-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVF_VADD => fp_add(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)), - FWVF_VSUB => fp_sub(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)), - FWVF_VMUL => fp_mul(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVF_VADD => fp_add(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)), + FWVF_VSUB => fp_sub(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)), + FWVF_VMUL => fp_mul(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwmul.vv.yaml b/arch/inst/V/vfwmul.vv.yaml index 7ee8a0bc3..8e07e64d7 100644 --- a/arch/inst/V/vfwmul.vv.yaml +++ b/arch/inst/V/vfwmul.vv.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwmul.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 111000-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwmul.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 111000-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVV_VADD => fp_add(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])), - FWVV_VSUB => fp_sub(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])), - FWVV_VMUL => fp_mul(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVV_VADD => fp_add(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])), + FWVV_VSUB => fp_sub(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])), + FWVV_VMUL => fp_mul(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwnmacc.vf.yaml b/arch/inst/V/vfwnmacc.vf.yaml index e046e240a..d65aeb070 100644 --- a/arch/inst/V/vfwnmacc.vf.yaml +++ b/arch/inst/V/vfwnmacc.vf.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwnmacc.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 111101-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwnmacc.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 111101-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVF_VMACC => fp_muladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), - FWVF_VNMACC => fp_nmulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), - FWVF_VMSAC => fp_mulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), - FWVF_VNMSAC => fp_nmuladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVF_VMACC => fp_muladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), + FWVF_VNMACC => fp_nmulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), + FWVF_VMSAC => fp_mulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), + FWVF_VNMSAC => fp_nmuladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwnmacc.vv.yaml b/arch/inst/V/vfwnmacc.vv.yaml index b571cbbe5..f67004249 100644 --- a/arch/inst/V/vfwnmacc.vv.yaml +++ b/arch/inst/V/vfwnmacc.vv.yaml @@ -1,75 +1,76 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwnmacc.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 111101-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwnmacc.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 111101-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVV_VMACC => fp_muladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), - FWVV_VNMACC => fp_nmulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), - FWVV_VMSAC => fp_mulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), - FWVV_VNMSAC => fp_nmuladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVV_VMACC => fp_muladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), + FWVV_VNMACC => fp_nmulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), + FWVV_VMSAC => fp_mulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), + FWVV_VNMSAC => fp_nmuladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwnmsac.vf.yaml b/arch/inst/V/vfwnmsac.vf.yaml index 45f6ef052..42e73c725 100644 --- a/arch/inst/V/vfwnmsac.vf.yaml +++ b/arch/inst/V/vfwnmsac.vf.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwnmsac.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 111111-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwnmsac.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 111111-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVF_VMACC => fp_muladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), - FWVF_VNMACC => fp_nmulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), - FWVF_VMSAC => fp_mulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), - FWVF_VNMSAC => fp_nmuladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVF_VMACC => fp_muladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), + FWVF_VNMACC => fp_nmulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), + FWVF_VMSAC => fp_mulsub(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]), + FWVF_VNMSAC => fp_nmuladd(rm_3b, fp_widen(rs1_val), fp_widen(vs2_val[i]), vd_val[i]) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwnmsac.vv.yaml b/arch/inst/V/vfwnmsac.vv.yaml index 869687f1c..4ab4e7dfc 100644 --- a/arch/inst/V/vfwnmsac.vv.yaml +++ b/arch/inst/V/vfwnmsac.vv.yaml @@ -1,75 +1,76 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwnmsac.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 111111-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwnmsac.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 111111-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVV_VMACC => fp_muladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), - FWVV_VNMACC => fp_nmulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), - FWVV_VMSAC => fp_mulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), - FWVV_VNMSAC => fp_nmuladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVV_VMACC => fp_muladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), + FWVV_VNMACC => fp_nmulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), + FWVV_VMSAC => fp_mulsub(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]), + FWVV_VNMSAC => fp_nmuladd(rm_3b, fp_widen(vs1_val[i]), fp_widen(vs2_val[i]), vd_val[i]) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwredosum.vs.yaml b/arch/inst/V/vfwredosum.vs.yaml index de96d140e..86b130f17 100644 --- a/arch/inst/V/vfwredosum.vs.yaml +++ b/arch/inst/V/vfwredosum.vs.yaml @@ -1,43 +1,44 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwredosum.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110011-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwredosum.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110011-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - - if funct6 == FVV_VFWREDOSUM | funct6 == FVV_VFWREDUSUM then - process_rfvv_widen(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) - else - process_rfvv_single(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if funct6 == FVV_VFWREDOSUM | funct6 == FVV_VFWREDUSUM then + process_rfvv_widen(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) + else + process_rfvv_single(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) + } + diff --git a/arch/inst/V/vfwredusum.vs.yaml b/arch/inst/V/vfwredusum.vs.yaml index 2369716e2..4e076feea 100644 --- a/arch/inst/V/vfwredusum.vs.yaml +++ b/arch/inst/V/vfwredusum.vs.yaml @@ -1,43 +1,44 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwredusum.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110001-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwredusum.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110001-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - - if funct6 == FVV_VFWREDOSUM | funct6 == FVV_VFWREDUSUM then - process_rfvv_widen(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) - else - process_rfvv_single(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if funct6 == FVV_VFWREDOSUM | funct6 == FVV_VFWREDUSUM then + process_rfvv_widen(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) + else + process_rfvv_single(funct6, vm, vs2, vs1, vd, num_elem_vs, SEW, LMUL_pow) + } + diff --git a/arch/inst/V/vfwsub.vf.yaml b/arch/inst/V/vfwsub.vf.yaml index d114fc532..6ebf50ccd 100644 --- a/arch/inst/V/vfwsub.vf.yaml +++ b/arch/inst/V/vfwsub.vf.yaml @@ -1,73 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwsub.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 110010-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwsub.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 110010-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVF_VADD => fp_add(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)), - FWVF_VSUB => fp_sub(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)), - FWVF_VMUL => fp_mul(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVF_VADD => fp_add(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)), + FWVF_VSUB => fp_sub(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)), + FWVF_VMUL => fp_mul(rm_3b, fp_widen(vs2_val[i]), fp_widen(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwsub.vv.yaml b/arch/inst/V/vfwsub.vv.yaml index 11ab418e2..31b111c9e 100644 --- a/arch/inst/V/vfwsub.vv.yaml +++ b/arch/inst/V/vfwsub.vv.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwsub.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110010-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwsub.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110010-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWVV_VADD => fp_add(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])), - FWVV_VSUB => fp_sub(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])), - FWVV_VMUL => fp_mul(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWVV_VADD => fp_add(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])), + FWVV_VSUB => fp_sub(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])), + FWVV_VMUL => fp_mul(rm_3b, fp_widen(vs2_val[i]), fp_widen(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwsub.wf.yaml b/arch/inst/V/vfwsub.wf.yaml index 709a2f1d5..5ec7bd5d3 100644 --- a/arch/inst/V/vfwsub.wf.yaml +++ b/arch/inst/V/vfwsub.wf.yaml @@ -1,71 +1,72 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwsub.wf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 110110-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwsub.wf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 110110-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWF_VADD => fp_add(rm_3b, vs2_val[i], fp_widen(rs1_val)), - FWF_VSUB => fp_sub(rm_3b, vs2_val[i], fp_widen(rs1_val)) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWF_VADD => fp_add(rm_3b, vs2_val[i], fp_widen(rs1_val)), + FWF_VSUB => fp_sub(rm_3b, vs2_val[i], fp_widen(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vfwsub.wv.yaml b/arch/inst/V/vfwsub.wv.yaml index 9b892adf3..f60f19a6a 100644 --- a/arch/inst/V/vfwsub.wv.yaml +++ b/arch/inst/V/vfwsub.wv.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwsub.wv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110110-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwsub.wv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110110-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW >= 16 & SEW_widen <= 64); - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - FWV_VADD => fp_add(rm_3b, vs2_val[i], fp_widen(vs1_val[i])), - FWV_VSUB => fp_sub(rm_3b, vs2_val[i], fp_widen(vs1_val[i])) - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW >= 16 & SEW_widen <= 64); + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + FWV_VADD => fp_add(rm_3b, vs2_val[i], fp_widen(vs1_val[i])), + FWV_VSUB => fp_sub(rm_3b, vs2_val[i], fp_widen(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vid.v.yaml b/arch/inst/V/vid.v.yaml index 21e678852..85f143afa 100644 --- a/arch/inst/V/vid.v.yaml +++ b/arch/inst/V/vid.v.yaml @@ -1,54 +1,55 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vid.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vd - encoding: - match: 010100-0000010001010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vid.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vd +encoding: + match: 010100-0000010001010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then result[i] = to_bits(SEW, i) - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then result[i] = to_bits(SEW, i) + }; + + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/viota.m.yaml b/arch/inst/V/viota.m.yaml index 991de765e..f4b1e376e 100644 --- a/arch/inst/V/viota.m.yaml +++ b/arch/inst/V/viota.m.yaml @@ -1,62 +1,63 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -viota.m: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010100------10000010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: viota.m +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010100------10000010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) | not(assert_vstart(0)) | vd == vs2 - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - sum : int = 0; - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = to_bits(SEW, sum); - if vs2_val[i] then sum = sum + 1 - } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_normal(vd, vm) | not(assert_vstart(0)) | vd == vs2 + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + sum : int = 0; + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = to_bits(SEW, sum); + if vs2_val[i] then sum = sum + 1 + } + }; + + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vl1re16.v.yaml b/arch/inst/V/vl1re16.v.yaml index 680b2898d..2d2c4c2eb 100644 --- a/arch/inst/V/vl1re16.v.yaml +++ b/arch/inst/V/vl1re16.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl1re16.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 000000101000-----101-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl1re16.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 000000101000-----101-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl1re32.v.yaml b/arch/inst/V/vl1re32.v.yaml index eda61a332..e04d176d6 100644 --- a/arch/inst/V/vl1re32.v.yaml +++ b/arch/inst/V/vl1re32.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl1re32.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 000000101000-----110-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl1re32.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 000000101000-----110-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl1re64.v.yaml b/arch/inst/V/vl1re64.v.yaml index 11a9647cc..b45371d96 100644 --- a/arch/inst/V/vl1re64.v.yaml +++ b/arch/inst/V/vl1re64.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl1re64.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 000000101000-----111-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl1re64.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 000000101000-----111-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl1re8.v.yaml b/arch/inst/V/vl1re8.v.yaml index 06deb98aa..8cef1447f 100644 --- a/arch/inst/V/vl1re8.v.yaml +++ b/arch/inst/V/vl1re8.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl1re8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 000000101000-----000-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl1re8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 000000101000-----000-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl2re16.v.yaml b/arch/inst/V/vl2re16.v.yaml index 38dfb4087..ff73f66ce 100644 --- a/arch/inst/V/vl2re16.v.yaml +++ b/arch/inst/V/vl2re16.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl2re16.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 001000101000-----101-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl2re16.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 001000101000-----101-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl2re32.v.yaml b/arch/inst/V/vl2re32.v.yaml index f0c33edc3..3e258e9cc 100644 --- a/arch/inst/V/vl2re32.v.yaml +++ b/arch/inst/V/vl2re32.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl2re32.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 001000101000-----110-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl2re32.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 001000101000-----110-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl2re64.v.yaml b/arch/inst/V/vl2re64.v.yaml index 1525047fa..06d9c4ba1 100644 --- a/arch/inst/V/vl2re64.v.yaml +++ b/arch/inst/V/vl2re64.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl2re64.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 001000101000-----111-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl2re64.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 001000101000-----111-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl2re8.v.yaml b/arch/inst/V/vl2re8.v.yaml index f097d9ed2..4820ef3fa 100644 --- a/arch/inst/V/vl2re8.v.yaml +++ b/arch/inst/V/vl2re8.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl2re8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 001000101000-----000-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl2re8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 001000101000-----000-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl4re16.v.yaml b/arch/inst/V/vl4re16.v.yaml index d073ea6c0..1d091962f 100644 --- a/arch/inst/V/vl4re16.v.yaml +++ b/arch/inst/V/vl4re16.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl4re16.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 011000101000-----101-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl4re16.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 011000101000-----101-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl4re32.v.yaml b/arch/inst/V/vl4re32.v.yaml index fb0db3176..e2caa0c2c 100644 --- a/arch/inst/V/vl4re32.v.yaml +++ b/arch/inst/V/vl4re32.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl4re32.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 011000101000-----110-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl4re32.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 011000101000-----110-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl4re64.v.yaml b/arch/inst/V/vl4re64.v.yaml index 7ded78d54..01b32c48a 100644 --- a/arch/inst/V/vl4re64.v.yaml +++ b/arch/inst/V/vl4re64.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl4re64.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 011000101000-----111-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl4re64.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 011000101000-----111-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl4re8.v.yaml b/arch/inst/V/vl4re8.v.yaml index a3e91acd7..a56cc57e5 100644 --- a/arch/inst/V/vl4re8.v.yaml +++ b/arch/inst/V/vl4re8.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl4re8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 011000101000-----000-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl4re8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 011000101000-----000-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl8re16.v.yaml b/arch/inst/V/vl8re16.v.yaml index 1748bfe65..3a9d1b0ae 100644 --- a/arch/inst/V/vl8re16.v.yaml +++ b/arch/inst/V/vl8re16.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl8re16.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 111000101000-----101-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl8re16.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 111000101000-----101-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl8re32.v.yaml b/arch/inst/V/vl8re32.v.yaml index eb4032221..747cf5438 100644 --- a/arch/inst/V/vl8re32.v.yaml +++ b/arch/inst/V/vl8re32.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl8re32.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 111000101000-----110-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl8re32.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 111000101000-----110-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl8re64.v.yaml b/arch/inst/V/vl8re64.v.yaml index 948bf1d1f..3c32d3562 100644 --- a/arch/inst/V/vl8re64.v.yaml +++ b/arch/inst/V/vl8re64.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl8re64.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 111000101000-----111-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl8re64.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 111000101000-----111-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vl8re8.v.yaml b/arch/inst/V/vl8re8.v.yaml index 843492632..f424ac472 100644 --- a/arch/inst/V/vl8re8.v.yaml +++ b/arch/inst/V/vl8re8.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vl8re8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 111000101000-----000-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vl8re8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 111000101000-----000-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vle16.v.yaml b/arch/inst/V/vle16.v.yaml index afa6628d3..993937d6e 100644 --- a/arch/inst/V/vle16.v.yaml +++ b/arch/inst/V/vle16.v.yaml @@ -1,45 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vle16.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs1, vd - encoding: - match: 000000-00000-----101-----0000111 - variables: - - name: vm - location: 25-25 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vle16.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs1, vd +encoding: + match: 000000-00000-----101-----0000111 + variables: + - name: vm + location: 25-25 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); /* # of element of each register group */ - let nf_int = nfields_int(nf); - - if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlseg(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); /* # of element of each register group */ + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlseg(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vle16ff.v.yaml b/arch/inst/V/vle16ff.v.yaml index 23e55e5d1..e27dfed29 100644 --- a/arch/inst/V/vle16ff.v.yaml +++ b/arch/inst/V/vle16ff.v.yaml @@ -1,45 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vle16ff.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs1, vd - encoding: - match: 000000-10000-----101-----0000111 - variables: - - name: vm - location: 25-25 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vle16ff.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs1, vd +encoding: + match: 000000-10000-----101-----0000111 + variables: + - name: vm + location: 25-25 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlsegff(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlsegff(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vle32.v.yaml b/arch/inst/V/vle32.v.yaml index 8fb2887da..9106cbb53 100644 --- a/arch/inst/V/vle32.v.yaml +++ b/arch/inst/V/vle32.v.yaml @@ -1,45 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vle32.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs1, vd - encoding: - match: 000000-00000-----110-----0000111 - variables: - - name: vm - location: 25-25 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vle32.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs1, vd +encoding: + match: 000000-00000-----110-----0000111 + variables: + - name: vm + location: 25-25 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); /* # of element of each register group */ - let nf_int = nfields_int(nf); - - if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlseg(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); /* # of element of each register group */ + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlseg(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vle32ff.v.yaml b/arch/inst/V/vle32ff.v.yaml index 2d84eb69d..c19956a1b 100644 --- a/arch/inst/V/vle32ff.v.yaml +++ b/arch/inst/V/vle32ff.v.yaml @@ -1,45 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vle32ff.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs1, vd - encoding: - match: 000000-10000-----110-----0000111 - variables: - - name: vm - location: 25-25 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vle32ff.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs1, vd +encoding: + match: 000000-10000-----110-----0000111 + variables: + - name: vm + location: 25-25 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlsegff(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlsegff(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vle64.v.yaml b/arch/inst/V/vle64.v.yaml index c43ad5b13..5f455f5a7 100644 --- a/arch/inst/V/vle64.v.yaml +++ b/arch/inst/V/vle64.v.yaml @@ -1,45 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vle64.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs1, vd - encoding: - match: 000000-00000-----111-----0000111 - variables: - - name: vm - location: 25-25 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vle64.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs1, vd +encoding: + match: 000000-00000-----111-----0000111 + variables: + - name: vm + location: 25-25 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); /* # of element of each register group */ - let nf_int = nfields_int(nf); - - if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlseg(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); /* # of element of each register group */ + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlseg(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vle64ff.v.yaml b/arch/inst/V/vle64ff.v.yaml index 67c096110..acafd2aa6 100644 --- a/arch/inst/V/vle64ff.v.yaml +++ b/arch/inst/V/vle64ff.v.yaml @@ -1,45 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vle64ff.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs1, vd - encoding: - match: 000000-10000-----111-----0000111 - variables: - - name: vm - location: 25-25 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vle64ff.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs1, vd +encoding: + match: 000000-10000-----111-----0000111 + variables: + - name: vm + location: 25-25 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlsegff(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlsegff(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vle8.v.yaml b/arch/inst/V/vle8.v.yaml index 1ad68bc1d..12169fac5 100644 --- a/arch/inst/V/vle8.v.yaml +++ b/arch/inst/V/vle8.v.yaml @@ -1,45 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vle8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs1, vd - encoding: - match: 000000-00000-----000-----0000111 - variables: - - name: vm - location: 25-25 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vle8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs1, vd +encoding: + match: 000000-00000-----000-----0000111 + variables: + - name: vm + location: 25-25 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); /* # of element of each register group */ - let nf_int = nfields_int(nf); - - if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlseg(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); /* # of element of each register group */ + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlseg(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vle8ff.v.yaml b/arch/inst/V/vle8ff.v.yaml index e7f1fde3e..58faf7fe8 100644 --- a/arch/inst/V/vle8ff.v.yaml +++ b/arch/inst/V/vle8ff.v.yaml @@ -1,45 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vle8ff.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs1, vd - encoding: - match: 000000-10000-----000-----0000111 - variables: - - name: vm - location: 25-25 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vle8ff.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs1, vd +encoding: + match: 000000-10000-----000-----0000111 + variables: + - name: vm + location: 25-25 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlsegff(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlsegff(nf_int, vm, vd, load_width_bytes, rs1, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vlm.v.yaml b/arch/inst/V/vlm.v.yaml index 39b8607ae..87096feca 100644 --- a/arch/inst/V/vlm.v.yaml +++ b/arch/inst/V/vlm.v.yaml @@ -1,41 +1,42 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vlm.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 000000101011-----000-----0000111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vlm.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 000000101011-----000-----0000111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW = 8; - let EMUL_pow = 0; - let vl_val = unsigned(vl); - let evl : int = if vl_val % 8 == 0 then vl_val / 8 else vl_val / 8 + 1; /* the effective vector length is evl=ceil(vl/8) */ - let num_elem = get_num_elem(EMUL_pow, EEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - assert(evl >= 0); - process_vm(vd_or_vs3, rs1, num_elem, evl, op) - } +sail(): | + { + let EEW = 8; + let EMUL_pow = 0; + let vl_val = unsigned(vl); + let evl : int = if vl_val % 8 == 0 then vl_val / 8 else vl_val / 8 + 1; /* the effective vector length is evl=ceil(vl/8) */ + let num_elem = get_num_elem(EMUL_pow, EEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + assert(evl >= 0); + process_vm(vd_or_vs3, rs1, num_elem, evl, op) + } + diff --git a/arch/inst/V/vloxei16.v.yaml b/arch/inst/V/vloxei16.v.yaml index 8dcfa00a0..4c080f551 100644 --- a/arch/inst/V/vloxei16.v.yaml +++ b/arch/inst/V/vloxei16.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vloxei16.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000011-----------101-----0000111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vloxei16.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000011-----------101-----0000111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); - let nf_int = nfields_int(nf); - - if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 3) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 3) + } + diff --git a/arch/inst/V/vloxei32.v.yaml b/arch/inst/V/vloxei32.v.yaml index 998981d8f..61a158182 100644 --- a/arch/inst/V/vloxei32.v.yaml +++ b/arch/inst/V/vloxei32.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vloxei32.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000011-----------110-----0000111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vloxei32.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000011-----------110-----0000111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); - let nf_int = nfields_int(nf); - - if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 3) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 3) + } + diff --git a/arch/inst/V/vloxei64.v.yaml b/arch/inst/V/vloxei64.v.yaml index 1fba6c7d9..9e4ed92f7 100644 --- a/arch/inst/V/vloxei64.v.yaml +++ b/arch/inst/V/vloxei64.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vloxei64.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000011-----------111-----0000111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vloxei64.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000011-----------111-----0000111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); - let nf_int = nfields_int(nf); - - if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 3) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 3) + } + diff --git a/arch/inst/V/vloxei8.v.yaml b/arch/inst/V/vloxei8.v.yaml index 2226891cf..c3dfe99ee 100644 --- a/arch/inst/V/vloxei8.v.yaml +++ b/arch/inst/V/vloxei8.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vloxei8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000011-----------000-----0000111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vloxei8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000011-----------000-----0000111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); - let nf_int = nfields_int(nf); - - if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 3) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 3) + } + diff --git a/arch/inst/V/vlse16.v.yaml b/arch/inst/V/vlse16.v.yaml index 5f51b1a55..c5a7f1aa7 100644 --- a/arch/inst/V/vlse16.v.yaml +++ b/arch/inst/V/vlse16.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vlse16.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs2, xs1, vd - encoding: - match: 000010-----------101-----0000111 - variables: - - name: vm - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vlse16.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs2, xs1, vd +encoding: + match: 000010-----------101-----0000111 + variables: + - name: vm + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlsseg(nf_int, vm, vd, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlsseg(nf_int, vm, vd, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vlse32.v.yaml b/arch/inst/V/vlse32.v.yaml index dc324e8df..01849349b 100644 --- a/arch/inst/V/vlse32.v.yaml +++ b/arch/inst/V/vlse32.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vlse32.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs2, xs1, vd - encoding: - match: 000010-----------110-----0000111 - variables: - - name: vm - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vlse32.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs2, xs1, vd +encoding: + match: 000010-----------110-----0000111 + variables: + - name: vm + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlsseg(nf_int, vm, vd, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlsseg(nf_int, vm, vd, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vlse64.v.yaml b/arch/inst/V/vlse64.v.yaml index c6f7ee030..d24b18466 100644 --- a/arch/inst/V/vlse64.v.yaml +++ b/arch/inst/V/vlse64.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vlse64.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs2, xs1, vd - encoding: - match: 000010-----------111-----0000111 - variables: - - name: vm - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vlse64.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs2, xs1, vd +encoding: + match: 000010-----------111-----0000111 + variables: + - name: vm + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlsseg(nf_int, vm, vd, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlsseg(nf_int, vm, vd, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vlse8.v.yaml b/arch/inst/V/vlse8.v.yaml index 9e6c34a7c..bf7896550 100644 --- a/arch/inst/V/vlse8.v.yaml +++ b/arch/inst/V/vlse8.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vlse8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs2, xs1, vd - encoding: - match: 000010-----------000-----0000111 - variables: - - name: vm - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vlse8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs2, xs1, vd +encoding: + match: 000010-----------000-----0000111 + variables: + - name: vm + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlsseg(nf_int, vm, vd, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_load(vd, vm, nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlsseg(nf_int, vm, vd, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vluxei16.v.yaml b/arch/inst/V/vluxei16.v.yaml index a0ebceea6..2d4405c37 100644 --- a/arch/inst/V/vluxei16.v.yaml +++ b/arch/inst/V/vluxei16.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vluxei16.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000001-----------101-----0000111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vluxei16.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000001-----------101-----0000111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); - let nf_int = nfields_int(nf); - - if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) + } + diff --git a/arch/inst/V/vluxei32.v.yaml b/arch/inst/V/vluxei32.v.yaml index 6dc21fd23..617abc17c 100644 --- a/arch/inst/V/vluxei32.v.yaml +++ b/arch/inst/V/vluxei32.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vluxei32.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000001-----------110-----0000111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vluxei32.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000001-----------110-----0000111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); - let nf_int = nfields_int(nf); - - if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) + } + diff --git a/arch/inst/V/vluxei64.v.yaml b/arch/inst/V/vluxei64.v.yaml index c3ca6a55b..6889bc85c 100644 --- a/arch/inst/V/vluxei64.v.yaml +++ b/arch/inst/V/vluxei64.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vluxei64.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000001-----------111-----0000111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vluxei64.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000001-----------111-----0000111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); - let nf_int = nfields_int(nf); - - if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) + } + diff --git a/arch/inst/V/vluxei8.v.yaml b/arch/inst/V/vluxei8.v.yaml index e3b9db487..7d9422a60 100644 --- a/arch/inst/V/vluxei8.v.yaml +++ b/arch/inst/V/vluxei8.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vluxei8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000001-----------000-----0000111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vluxei8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000001-----------000-----0000111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); - let nf_int = nfields_int(nf); - - if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_load(vd, vm, nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vlxseg(nf_int, vm, vd, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) + } + diff --git a/arch/inst/V/vmacc.vv.yaml b/arch/inst/V/vmacc.vv.yaml index 706f61c67..2f962c1db 100644 --- a/arch/inst/V/vmacc.vv.yaml +++ b/arch/inst/V/vmacc.vv.yaml @@ -1,67 +1,68 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmacc.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101101-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmacc.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101101-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VMACC => get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0) + vd_val[i], - MVV_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0), - MVV_VMADD => get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) + vs2_val[i], - MVV_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VMACC => get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0) + vd_val[i], + MVV_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0), + MVV_VMADD => get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) + vs2_val[i], + MVV_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmacc.vx.yaml b/arch/inst/V/vmacc.vx.yaml index ac6842258..6ecc901da 100644 --- a/arch/inst/V/vmacc.vx.yaml +++ b/arch/inst/V/vmacc.vx.yaml @@ -1,67 +1,68 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmacc.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101101-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmacc.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101101-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VMACC => get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0) + vd_val[i], - MVX_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0), - MVX_VMADD => get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) + vs2_val[i], - MVX_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VMACC => get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0) + vd_val[i], + MVX_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0), + MVX_VMADD => get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) + vs2_val[i], + MVX_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmadc.vi.yaml b/arch/inst/V/vmadc.vi.yaml index ec950016b..27249cc47 100644 --- a/arch/inst/V/vmadc.vi.yaml +++ b/arch/inst/V/vmadc.vi.yaml @@ -1,62 +1,63 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmadc.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vd, imm - encoding: - match: 0100011----------011-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmadc.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vd, imm +encoding: + match: 0100011----------011-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VIMC_VMADC => unsigned(vs2_val[i]) + unsigned(imm_val) > 2 ^ SEW - 1 - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VIMC_VMADC => unsigned(vs2_val[i]) + unsigned(imm_val) > 2 ^ SEW - 1 + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmadc.vim.yaml b/arch/inst/V/vmadc.vim.yaml index 11d890fab..ffb08eb00 100644 --- a/arch/inst/V/vmadc.vim.yaml +++ b/arch/inst/V/vmadc.vim.yaml @@ -1,63 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmadc.vim: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vd, imm - encoding: - match: 0100010----------011-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmadc.vim +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vd, imm +encoding: + match: 0100010----------011-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VIM_VMADC => unsigned(vs2_val[i]) + unsigned(imm_val) + unsigned(bool_to_bits(vm_val[i])) > 2 ^ SEW - 1 - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VIM_VMADC => unsigned(vs2_val[i]) + unsigned(imm_val) + unsigned(bool_to_bits(vm_val[i])) > 2 ^ SEW - 1 + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmadc.vv.yaml b/arch/inst/V/vmadc.vv.yaml index ffff08972..f2dfe8614 100644 --- a/arch/inst/V/vmadc.vv.yaml +++ b/arch/inst/V/vmadc.vv.yaml @@ -1,63 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmadc.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0100011----------000-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmadc.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0100011----------000-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VVMC_VMADC => unsigned(vs2_val[i]) + unsigned(vs1_val[i]) > 2 ^ SEW - 1, - VVMC_VMSBC => unsigned(vs2_val[i]) - unsigned(vs1_val[i]) < 0 - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VVMC_VMADC => unsigned(vs2_val[i]) + unsigned(vs1_val[i]) > 2 ^ SEW - 1, + VVMC_VMSBC => unsigned(vs2_val[i]) - unsigned(vs1_val[i]) < 0 + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmadc.vvm.yaml b/arch/inst/V/vmadc.vvm.yaml index 443eefa49..5ad1bc2fe 100644 --- a/arch/inst/V/vmadc.vvm.yaml +++ b/arch/inst/V/vmadc.vvm.yaml @@ -1,64 +1,65 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmadc.vvm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0100010----------000-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmadc.vvm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0100010----------000-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VVM_VMADC => unsigned(vs2_val[i]) + unsigned(vs1_val[i]) + unsigned(bool_to_bits(vm_val[i])) > 2 ^ SEW - 1, - VVM_VMSBC => unsigned(vs2_val[i]) - unsigned(vs1_val[i]) - unsigned(bool_to_bits(vm_val[i])) < 0 - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VVM_VMADC => unsigned(vs2_val[i]) + unsigned(vs1_val[i]) + unsigned(bool_to_bits(vm_val[i])) > 2 ^ SEW - 1, + VVM_VMSBC => unsigned(vs2_val[i]) - unsigned(vs1_val[i]) - unsigned(bool_to_bits(vm_val[i])) < 0 + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmadc.vx.yaml b/arch/inst/V/vmadc.vx.yaml index 342a32f11..06689d0e7 100644 --- a/arch/inst/V/vmadc.vx.yaml +++ b/arch/inst/V/vmadc.vx.yaml @@ -1,63 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmadc.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, xs1, vd - encoding: - match: 0100011----------100-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmadc.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, xs1, vd +encoding: + match: 0100011----------100-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VXMC_VMADC => unsigned(vs2_val[i]) + unsigned(rs1_val) > 2 ^ SEW - 1, - VXMC_VMSBC => unsigned(vs2_val[i]) - unsigned(rs1_val) < 0 - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VXMC_VMADC => unsigned(vs2_val[i]) + unsigned(rs1_val) > 2 ^ SEW - 1, + VXMC_VMSBC => unsigned(vs2_val[i]) - unsigned(rs1_val) < 0 + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmadc.vxm.yaml b/arch/inst/V/vmadc.vxm.yaml index b8df482ef..4f9f699ca 100644 --- a/arch/inst/V/vmadc.vxm.yaml +++ b/arch/inst/V/vmadc.vxm.yaml @@ -1,64 +1,65 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmadc.vxm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, xs1, vd - encoding: - match: 0100010----------100-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmadc.vxm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, xs1, vd +encoding: + match: 0100010----------100-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VXM_VMADC => unsigned(vs2_val[i]) + unsigned(rs1_val) + unsigned(bool_to_bits(vm_val[i])) > 2 ^ SEW - 1, - VXM_VMSBC => unsigned(vs2_val[i]) - unsigned(rs1_val) - unsigned(bool_to_bits(vm_val[i])) < 0 - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VXM_VMADC => unsigned(vs2_val[i]) + unsigned(rs1_val) + unsigned(bool_to_bits(vm_val[i])) > 2 ^ SEW - 1, + VXM_VMSBC => unsigned(vs2_val[i]) - unsigned(rs1_val) - unsigned(bool_to_bits(vm_val[i])) < 0 + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmadd.vv.yaml b/arch/inst/V/vmadd.vv.yaml index 1c9e13db4..fda328eb3 100644 --- a/arch/inst/V/vmadd.vv.yaml +++ b/arch/inst/V/vmadd.vv.yaml @@ -1,67 +1,68 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmadd.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101001-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmadd.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101001-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VMACC => get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0) + vd_val[i], - MVV_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0), - MVV_VMADD => get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) + vs2_val[i], - MVV_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VMACC => get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0) + vd_val[i], + MVV_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0), + MVV_VMADD => get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) + vs2_val[i], + MVV_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmadd.vx.yaml b/arch/inst/V/vmadd.vx.yaml index 4a5e163d1..5600d21f1 100644 --- a/arch/inst/V/vmadd.vx.yaml +++ b/arch/inst/V/vmadd.vx.yaml @@ -1,67 +1,68 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmadd.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101001-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmadd.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101001-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VMACC => get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0) + vd_val[i], - MVX_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0), - MVX_VMADD => get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) + vs2_val[i], - MVX_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VMACC => get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0) + vd_val[i], + MVX_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0), + MVX_VMADD => get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) + vs2_val[i], + MVX_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmand.mm.yaml b/arch/inst/V/vmand.mm.yaml index 468341df5..0897e5ad0 100644 --- a/arch/inst/V/vmand.mm.yaml +++ b/arch/inst/V/vmand.mm.yaml @@ -1,68 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmand.mm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0110011----------010-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmand.mm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0110011----------010-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = unsigned(vlenb) * 8; - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); - let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, 0, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MM_VMAND => vs2_val[i] & vs1_val[i], - MM_VMNAND => not(vs2_val[i] & vs1_val[i]), - MM_VMANDNOT => vs2_val[i] & not(vs1_val[i]), - MM_VMXOR => vs2_val[i] != vs1_val[i], - MM_VMOR => vs2_val[i] | vs1_val[i], - MM_VMNOR => not(vs2_val[i] | vs1_val[i]), - MM_VMORNOT => vs2_val[i] | not(vs1_val[i]), - MM_VMXNOR => vs2_val[i] == vs1_val[i] - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = unsigned(vlenb) * 8; + + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); + let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, 0, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MM_VMAND => vs2_val[i] & vs1_val[i], + MM_VMNAND => not(vs2_val[i] & vs1_val[i]), + MM_VMANDNOT => vs2_val[i] & not(vs1_val[i]), + MM_VMXOR => vs2_val[i] != vs1_val[i], + MM_VMOR => vs2_val[i] | vs1_val[i], + MM_VMNOR => not(vs2_val[i] | vs1_val[i]), + MM_VMORNOT => vs2_val[i] | not(vs1_val[i]), + MM_VMXNOR => vs2_val[i] == vs1_val[i] } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmandn.mm.yaml b/arch/inst/V/vmandn.mm.yaml index 45c27d6d9..a5dd1ba9a 100644 --- a/arch/inst/V/vmandn.mm.yaml +++ b/arch/inst/V/vmandn.mm.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmandn.mm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0110001----------010-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmandn.mm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0110001----------010-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vmax.vv.yaml b/arch/inst/V/vmax.vv.yaml index d08f9a2b3..ed446c2ae 100644 --- a/arch/inst/V/vmax.vv.yaml +++ b/arch/inst/V/vmax.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmax.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000111-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmax.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000111-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmax.vx.yaml b/arch/inst/V/vmax.vx.yaml index b190f6c46..796bf3f12 100644 --- a/arch/inst/V/vmax.vx.yaml +++ b/arch/inst/V/vmax.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmax.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000111-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmax.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000111-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmaxu.vv.yaml b/arch/inst/V/vmaxu.vv.yaml index fb79c7030..1e3b423da 100644 --- a/arch/inst/V/vmaxu.vv.yaml +++ b/arch/inst/V/vmaxu.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmaxu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000110-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmaxu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000110-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmaxu.vx.yaml b/arch/inst/V/vmaxu.vx.yaml index 1b5c3bfeb..86af7591a 100644 --- a/arch/inst/V/vmaxu.vx.yaml +++ b/arch/inst/V/vmaxu.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmaxu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000110-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmaxu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000110-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmerge.vim.yaml b/arch/inst/V/vmerge.vim.yaml index 15f48e389..a190535f3 100644 --- a/arch/inst/V/vmerge.vim.yaml +++ b/arch/inst/V/vmerge.vim.yaml @@ -1,69 +1,70 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmerge.vim: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vd, imm - encoding: - match: 0101110----------011-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmerge.vim +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vd, imm +encoding: + match: 0101110----------011-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let start_element = get_start_element(); - let end_element = get_end_element(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); /* max(VLMAX,VLEN/SEW)) */ - let real_num_elem = if LMUL_pow >= 0 then num_elem else num_elem / (0 - LMUL_pow); /* VLMAX */ - - if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - - let tail_ag : agtype = get_vtype_vta(); - foreach (i from 0 to (num_elem - 1)) { - if i < start_element then { - result[i] = vd_val[i] - } else if i > end_element | i >= real_num_elem then { - result[i] = match tail_ag { - UNDISTURBED => vd_val[i], - AGNOSTIC => vd_val[i] /* TODO: configuration support */ - } - } else { - /* the merge operates on all body elements */ - result[i] = if vm_val[i] then imm_val else vs2_val[i] +sail(): | + { + let start_element = get_start_element(); + let end_element = get_end_element(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); /* max(VLMAX,VLEN/SEW)) */ + let real_num_elem = if LMUL_pow >= 0 then num_elem else num_elem / (0 - LMUL_pow); /* VLMAX */ + + if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + + let tail_ag : agtype = get_vtype_vta(); + foreach (i from 0 to (num_elem - 1)) { + if i < start_element then { + result[i] = vd_val[i] + } else if i > end_element | i >= real_num_elem then { + result[i] = match tail_ag { + UNDISTURBED => vd_val[i], + AGNOSTIC => vd_val[i] /* TODO: configuration support */ } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } else { + /* the merge operates on all body elements */ + result[i] = if vm_val[i] then imm_val else vs2_val[i] + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmerge.vvm.yaml b/arch/inst/V/vmerge.vvm.yaml index f8c977d1f..12977cc00 100644 --- a/arch/inst/V/vmerge.vvm.yaml +++ b/arch/inst/V/vmerge.vvm.yaml @@ -1,69 +1,70 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmerge.vvm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0101110----------000-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmerge.vvm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0101110----------000-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let start_element = get_start_element(); - let end_element = get_end_element(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); /* max(VLMAX,VLEN/SEW)) */ - let real_num_elem = if LMUL_pow >= 0 then num_elem else num_elem / (0 - LMUL_pow); /* VLMAX */ - - if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - - let tail_ag : agtype = get_vtype_vta(); - foreach (i from 0 to (num_elem - 1)) { - if i < start_element then { - result[i] = vd_val[i] - } else if i > end_element | i >= real_num_elem then { - result[i] = match tail_ag { - UNDISTURBED => vd_val[i], - AGNOSTIC => vd_val[i] /* TODO: configuration support */ - } - } else { - /* the merge operates on all body elements */ - result[i] = if vm_val[i] then vs1_val[i] else vs2_val[i] +sail(): | + { + let start_element = get_start_element(); + let end_element = get_end_element(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); /* max(VLMAX,VLEN/SEW)) */ + let real_num_elem = if LMUL_pow >= 0 then num_elem else num_elem / (0 - LMUL_pow); /* VLMAX */ + + if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + + let tail_ag : agtype = get_vtype_vta(); + foreach (i from 0 to (num_elem - 1)) { + if i < start_element then { + result[i] = vd_val[i] + } else if i > end_element | i >= real_num_elem then { + result[i] = match tail_ag { + UNDISTURBED => vd_val[i], + AGNOSTIC => vd_val[i] /* TODO: configuration support */ } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } else { + /* the merge operates on all body elements */ + result[i] = if vm_val[i] then vs1_val[i] else vs2_val[i] + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmerge.vxm.yaml b/arch/inst/V/vmerge.vxm.yaml index 0a14ea854..d40cf5031 100644 --- a/arch/inst/V/vmerge.vxm.yaml +++ b/arch/inst/V/vmerge.vxm.yaml @@ -1,69 +1,70 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmerge.vxm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, xs1, vd - encoding: - match: 0101110----------100-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmerge.vxm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, xs1, vd +encoding: + match: 0101110----------100-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let start_element = get_start_element(); - let end_element = get_end_element(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); /* max(VLMAX,VLEN/SEW)) */ - let real_num_elem = if LMUL_pow >= 0 then num_elem else num_elem / (0 - LMUL_pow); /* VLMAX */ - - if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - - let tail_ag : agtype = get_vtype_vta(); - foreach (i from 0 to (num_elem - 1)) { - if i < start_element then { - result[i] = vd_val[i] - } else if i > end_element | i >= real_num_elem then { - result[i] = match tail_ag { - UNDISTURBED => vd_val[i], - AGNOSTIC => vd_val[i] /* TODO: configuration support */ - } - } else { - /* the merge operates on all body elements */ - result[i] = if vm_val[i] then rs1_val else vs2_val[i] +sail(): | + { + let start_element = get_start_element(); + let end_element = get_end_element(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); /* max(VLMAX,VLEN/SEW)) */ + let real_num_elem = if LMUL_pow >= 0 then num_elem else num_elem / (0 - LMUL_pow); /* VLMAX */ + + if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + + let tail_ag : agtype = get_vtype_vta(); + foreach (i from 0 to (num_elem - 1)) { + if i < start_element then { + result[i] = vd_val[i] + } else if i > end_element | i >= real_num_elem then { + result[i] = match tail_ag { + UNDISTURBED => vd_val[i], + AGNOSTIC => vd_val[i] /* TODO: configuration support */ } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } else { + /* the merge operates on all body elements */ + result[i] = if vm_val[i] then rs1_val else vs2_val[i] + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmfeq.vf.yaml b/arch/inst/V/vmfeq.vf.yaml index dbc0d4383..cc637854e 100644 --- a/arch/inst/V/vmfeq.vf.yaml +++ b/arch/inst/V/vmfeq.vf.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmfeq.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011000-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmfeq.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011000-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VFM_VMFEQ => fp_eq(vs2_val[i], rs1_val), - VFM_VMFNE => ~(fp_eq(vs2_val[i], rs1_val)), - VFM_VMFLE => fp_le(vs2_val[i], rs1_val), - VFM_VMFLT => fp_lt(vs2_val[i], rs1_val), - VFM_VMFGE => fp_ge(vs2_val[i], rs1_val), - VFM_VMFGT => fp_gt(vs2_val[i], rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VFM_VMFEQ => fp_eq(vs2_val[i], rs1_val), + VFM_VMFNE => ~(fp_eq(vs2_val[i], rs1_val)), + VFM_VMFLE => fp_le(vs2_val[i], rs1_val), + VFM_VMFLT => fp_lt(vs2_val[i], rs1_val), + VFM_VMFGE => fp_ge(vs2_val[i], rs1_val), + VFM_VMFGT => fp_gt(vs2_val[i], rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmfeq.vv.yaml b/arch/inst/V/vmfeq.vv.yaml index 4072b65a6..131d35caa 100644 --- a/arch/inst/V/vmfeq.vv.yaml +++ b/arch/inst/V/vmfeq.vv.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmfeq.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 011000-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmfeq.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 011000-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - FVVM_VMFEQ => fp_eq(vs2_val[i], vs1_val[i]), - FVVM_VMFNE => ~(fp_eq(vs2_val[i], vs1_val[i])), - FVVM_VMFLE => fp_le(vs2_val[i], vs1_val[i]), - FVVM_VMFLT => fp_lt(vs2_val[i], vs1_val[i]) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + FVVM_VMFEQ => fp_eq(vs2_val[i], vs1_val[i]), + FVVM_VMFNE => ~(fp_eq(vs2_val[i], vs1_val[i])), + FVVM_VMFLE => fp_le(vs2_val[i], vs1_val[i]), + FVVM_VMFLT => fp_lt(vs2_val[i], vs1_val[i]) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmfge.vf.yaml b/arch/inst/V/vmfge.vf.yaml index 6534a6bb8..c449201be 100644 --- a/arch/inst/V/vmfge.vf.yaml +++ b/arch/inst/V/vmfge.vf.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmfge.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011111-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmfge.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011111-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VFM_VMFEQ => fp_eq(vs2_val[i], rs1_val), - VFM_VMFNE => ~(fp_eq(vs2_val[i], rs1_val)), - VFM_VMFLE => fp_le(vs2_val[i], rs1_val), - VFM_VMFLT => fp_lt(vs2_val[i], rs1_val), - VFM_VMFGE => fp_ge(vs2_val[i], rs1_val), - VFM_VMFGT => fp_gt(vs2_val[i], rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VFM_VMFEQ => fp_eq(vs2_val[i], rs1_val), + VFM_VMFNE => ~(fp_eq(vs2_val[i], rs1_val)), + VFM_VMFLE => fp_le(vs2_val[i], rs1_val), + VFM_VMFLT => fp_lt(vs2_val[i], rs1_val), + VFM_VMFGE => fp_ge(vs2_val[i], rs1_val), + VFM_VMFGT => fp_gt(vs2_val[i], rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmfgt.vf.yaml b/arch/inst/V/vmfgt.vf.yaml index e99613633..3a7c121aa 100644 --- a/arch/inst/V/vmfgt.vf.yaml +++ b/arch/inst/V/vmfgt.vf.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmfgt.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011101-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmfgt.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011101-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VFM_VMFEQ => fp_eq(vs2_val[i], rs1_val), - VFM_VMFNE => ~(fp_eq(vs2_val[i], rs1_val)), - VFM_VMFLE => fp_le(vs2_val[i], rs1_val), - VFM_VMFLT => fp_lt(vs2_val[i], rs1_val), - VFM_VMFGE => fp_ge(vs2_val[i], rs1_val), - VFM_VMFGT => fp_gt(vs2_val[i], rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VFM_VMFEQ => fp_eq(vs2_val[i], rs1_val), + VFM_VMFNE => ~(fp_eq(vs2_val[i], rs1_val)), + VFM_VMFLE => fp_le(vs2_val[i], rs1_val), + VFM_VMFLT => fp_lt(vs2_val[i], rs1_val), + VFM_VMFGE => fp_ge(vs2_val[i], rs1_val), + VFM_VMFGT => fp_gt(vs2_val[i], rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmfle.vf.yaml b/arch/inst/V/vmfle.vf.yaml index 65344a65b..405a2073a 100644 --- a/arch/inst/V/vmfle.vf.yaml +++ b/arch/inst/V/vmfle.vf.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmfle.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011001-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmfle.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011001-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VFM_VMFEQ => fp_eq(vs2_val[i], rs1_val), - VFM_VMFNE => ~(fp_eq(vs2_val[i], rs1_val)), - VFM_VMFLE => fp_le(vs2_val[i], rs1_val), - VFM_VMFLT => fp_lt(vs2_val[i], rs1_val), - VFM_VMFGE => fp_ge(vs2_val[i], rs1_val), - VFM_VMFGT => fp_gt(vs2_val[i], rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VFM_VMFEQ => fp_eq(vs2_val[i], rs1_val), + VFM_VMFNE => ~(fp_eq(vs2_val[i], rs1_val)), + VFM_VMFLE => fp_le(vs2_val[i], rs1_val), + VFM_VMFLT => fp_lt(vs2_val[i], rs1_val), + VFM_VMFGE => fp_ge(vs2_val[i], rs1_val), + VFM_VMFGT => fp_gt(vs2_val[i], rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmfle.vv.yaml b/arch/inst/V/vmfle.vv.yaml index 1bdcdea2e..7937c5547 100644 --- a/arch/inst/V/vmfle.vv.yaml +++ b/arch/inst/V/vmfle.vv.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmfle.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 011001-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmfle.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 011001-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - FVVM_VMFEQ => fp_eq(vs2_val[i], vs1_val[i]), - FVVM_VMFNE => ~(fp_eq(vs2_val[i], vs1_val[i])), - FVVM_VMFLE => fp_le(vs2_val[i], vs1_val[i]), - FVVM_VMFLT => fp_lt(vs2_val[i], vs1_val[i]) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + FVVM_VMFEQ => fp_eq(vs2_val[i], vs1_val[i]), + FVVM_VMFNE => ~(fp_eq(vs2_val[i], vs1_val[i])), + FVVM_VMFLE => fp_le(vs2_val[i], vs1_val[i]), + FVVM_VMFLT => fp_lt(vs2_val[i], vs1_val[i]) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmflt.vf.yaml b/arch/inst/V/vmflt.vf.yaml index 8a4c8a94b..3260c4d26 100644 --- a/arch/inst/V/vmflt.vf.yaml +++ b/arch/inst/V/vmflt.vf.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmflt.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011011-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmflt.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011011-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VFM_VMFEQ => fp_eq(vs2_val[i], rs1_val), - VFM_VMFNE => ~(fp_eq(vs2_val[i], rs1_val)), - VFM_VMFLE => fp_le(vs2_val[i], rs1_val), - VFM_VMFLT => fp_lt(vs2_val[i], rs1_val), - VFM_VMFGE => fp_ge(vs2_val[i], rs1_val), - VFM_VMFGT => fp_gt(vs2_val[i], rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VFM_VMFEQ => fp_eq(vs2_val[i], rs1_val), + VFM_VMFNE => ~(fp_eq(vs2_val[i], rs1_val)), + VFM_VMFLE => fp_le(vs2_val[i], rs1_val), + VFM_VMFLT => fp_lt(vs2_val[i], rs1_val), + VFM_VMFGE => fp_ge(vs2_val[i], rs1_val), + VFM_VMFGT => fp_gt(vs2_val[i], rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmflt.vv.yaml b/arch/inst/V/vmflt.vv.yaml index aaf35ddf1..a89bab6ba 100644 --- a/arch/inst/V/vmflt.vv.yaml +++ b/arch/inst/V/vmflt.vv.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmflt.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 011011-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmflt.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 011011-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - FVVM_VMFEQ => fp_eq(vs2_val[i], vs1_val[i]), - FVVM_VMFNE => ~(fp_eq(vs2_val[i], vs1_val[i])), - FVVM_VMFLE => fp_le(vs2_val[i], vs1_val[i]), - FVVM_VMFLT => fp_lt(vs2_val[i], vs1_val[i]) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + FVVM_VMFEQ => fp_eq(vs2_val[i], vs1_val[i]), + FVVM_VMFNE => ~(fp_eq(vs2_val[i], vs1_val[i])), + FVVM_VMFLE => fp_le(vs2_val[i], vs1_val[i]), + FVVM_VMFLT => fp_lt(vs2_val[i], vs1_val[i]) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmfne.vf.yaml b/arch/inst/V/vmfne.vf.yaml index e9717ec82..f8dc41881 100644 --- a/arch/inst/V/vmfne.vf.yaml +++ b/arch/inst/V/vmfne.vf.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmfne.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011100-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmfne.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011100-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VFM_VMFEQ => fp_eq(vs2_val[i], rs1_val), - VFM_VMFNE => ~(fp_eq(vs2_val[i], rs1_val)), - VFM_VMFLE => fp_le(vs2_val[i], rs1_val), - VFM_VMFLT => fp_lt(vs2_val[i], rs1_val), - VFM_VMFGE => fp_ge(vs2_val[i], rs1_val), - VFM_VMFGT => fp_gt(vs2_val[i], rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar_fp(rs1, 'm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VFM_VMFEQ => fp_eq(vs2_val[i], rs1_val), + VFM_VMFNE => ~(fp_eq(vs2_val[i], rs1_val)), + VFM_VMFLE => fp_le(vs2_val[i], rs1_val), + VFM_VMFLT => fp_lt(vs2_val[i], rs1_val), + VFM_VMFGE => fp_ge(vs2_val[i], rs1_val), + VFM_VMFGT => fp_gt(vs2_val[i], rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmfne.vv.yaml b/arch/inst/V/vmfne.vv.yaml index 1d2c139a9..49052496c 100644 --- a/arch/inst/V/vmfne.vv.yaml +++ b/arch/inst/V/vmfne.vv.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmfne.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 011100-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmfne.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 011100-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let rm_3b = fcsr.FRM(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; - assert(SEW != 8); - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - FVVM_VMFEQ => fp_eq(vs2_val[i], vs1_val[i]), - FVVM_VMFNE => ~(fp_eq(vs2_val[i], vs1_val[i])), - FVVM_VMFLE => fp_le(vs2_val[i], vs1_val[i]), - FVVM_VMFLT => fp_lt(vs2_val[i], vs1_val[i]) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let rm_3b = fcsr.FRM(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_fp_vd_unmasked(SEW, rm_3b) then { handle_illegal(); return RETIRE_FAIL }; + assert(SEW != 8); + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + FVVM_VMFEQ => fp_eq(vs2_val[i], vs1_val[i]), + FVVM_VMFNE => ~(fp_eq(vs2_val[i], vs1_val[i])), + FVVM_VMFLE => fp_le(vs2_val[i], vs1_val[i]), + FVVM_VMFLT => fp_lt(vs2_val[i], vs1_val[i]) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmin.vv.yaml b/arch/inst/V/vmin.vv.yaml index f5fff3d66..77b5c4b75 100644 --- a/arch/inst/V/vmin.vv.yaml +++ b/arch/inst/V/vmin.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmin.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000101-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmin.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000101-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmin.vx.yaml b/arch/inst/V/vmin.vx.yaml index ecf1f1c5a..93b7149db 100644 --- a/arch/inst/V/vmin.vx.yaml +++ b/arch/inst/V/vmin.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmin.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000101-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmin.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000101-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vminu.vv.yaml b/arch/inst/V/vminu.vv.yaml index 99c8898ab..fb5523ec9 100644 --- a/arch/inst/V/vminu.vv.yaml +++ b/arch/inst/V/vminu.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vminu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000100-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vminu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000100-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vminu.vx.yaml b/arch/inst/V/vminu.vx.yaml index f985fd748..25835e6f8 100644 --- a/arch/inst/V/vminu.vx.yaml +++ b/arch/inst/V/vminu.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vminu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000100-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vminu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000100-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmnand.mm.yaml b/arch/inst/V/vmnand.mm.yaml index a7332e81c..8b81cd5e0 100644 --- a/arch/inst/V/vmnand.mm.yaml +++ b/arch/inst/V/vmnand.mm.yaml @@ -1,68 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmnand.mm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0111011----------010-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmnand.mm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0111011----------010-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = unsigned(vlenb) * 8; - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); - let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, 0, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MM_VMAND => vs2_val[i] & vs1_val[i], - MM_VMNAND => not(vs2_val[i] & vs1_val[i]), - MM_VMANDNOT => vs2_val[i] & not(vs1_val[i]), - MM_VMXOR => vs2_val[i] != vs1_val[i], - MM_VMOR => vs2_val[i] | vs1_val[i], - MM_VMNOR => not(vs2_val[i] | vs1_val[i]), - MM_VMORNOT => vs2_val[i] | not(vs1_val[i]), - MM_VMXNOR => vs2_val[i] == vs1_val[i] - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = unsigned(vlenb) * 8; + + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); + let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, 0, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MM_VMAND => vs2_val[i] & vs1_val[i], + MM_VMNAND => not(vs2_val[i] & vs1_val[i]), + MM_VMANDNOT => vs2_val[i] & not(vs1_val[i]), + MM_VMXOR => vs2_val[i] != vs1_val[i], + MM_VMOR => vs2_val[i] | vs1_val[i], + MM_VMNOR => not(vs2_val[i] | vs1_val[i]), + MM_VMORNOT => vs2_val[i] | not(vs1_val[i]), + MM_VMXNOR => vs2_val[i] == vs1_val[i] } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmnor.mm.yaml b/arch/inst/V/vmnor.mm.yaml index fa053e69c..6666bd9a5 100644 --- a/arch/inst/V/vmnor.mm.yaml +++ b/arch/inst/V/vmnor.mm.yaml @@ -1,68 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmnor.mm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0111101----------010-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmnor.mm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0111101----------010-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = unsigned(vlenb) * 8; - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); - let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, 0, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MM_VMAND => vs2_val[i] & vs1_val[i], - MM_VMNAND => not(vs2_val[i] & vs1_val[i]), - MM_VMANDNOT => vs2_val[i] & not(vs1_val[i]), - MM_VMXOR => vs2_val[i] != vs1_val[i], - MM_VMOR => vs2_val[i] | vs1_val[i], - MM_VMNOR => not(vs2_val[i] | vs1_val[i]), - MM_VMORNOT => vs2_val[i] | not(vs1_val[i]), - MM_VMXNOR => vs2_val[i] == vs1_val[i] - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = unsigned(vlenb) * 8; + + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); + let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, 0, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MM_VMAND => vs2_val[i] & vs1_val[i], + MM_VMNAND => not(vs2_val[i] & vs1_val[i]), + MM_VMANDNOT => vs2_val[i] & not(vs1_val[i]), + MM_VMXOR => vs2_val[i] != vs1_val[i], + MM_VMOR => vs2_val[i] | vs1_val[i], + MM_VMNOR => not(vs2_val[i] | vs1_val[i]), + MM_VMORNOT => vs2_val[i] | not(vs1_val[i]), + MM_VMXNOR => vs2_val[i] == vs1_val[i] } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmor.mm.yaml b/arch/inst/V/vmor.mm.yaml index c0900fa96..4997ebe69 100644 --- a/arch/inst/V/vmor.mm.yaml +++ b/arch/inst/V/vmor.mm.yaml @@ -1,68 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmor.mm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0110101----------010-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmor.mm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0110101----------010-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = unsigned(vlenb) * 8; - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); - let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, 0, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MM_VMAND => vs2_val[i] & vs1_val[i], - MM_VMNAND => not(vs2_val[i] & vs1_val[i]), - MM_VMANDNOT => vs2_val[i] & not(vs1_val[i]), - MM_VMXOR => vs2_val[i] != vs1_val[i], - MM_VMOR => vs2_val[i] | vs1_val[i], - MM_VMNOR => not(vs2_val[i] | vs1_val[i]), - MM_VMORNOT => vs2_val[i] | not(vs1_val[i]), - MM_VMXNOR => vs2_val[i] == vs1_val[i] - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = unsigned(vlenb) * 8; + + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); + let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, 0, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MM_VMAND => vs2_val[i] & vs1_val[i], + MM_VMNAND => not(vs2_val[i] & vs1_val[i]), + MM_VMANDNOT => vs2_val[i] & not(vs1_val[i]), + MM_VMXOR => vs2_val[i] != vs1_val[i], + MM_VMOR => vs2_val[i] | vs1_val[i], + MM_VMNOR => not(vs2_val[i] | vs1_val[i]), + MM_VMORNOT => vs2_val[i] | not(vs1_val[i]), + MM_VMXNOR => vs2_val[i] == vs1_val[i] } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmorn.mm.yaml b/arch/inst/V/vmorn.mm.yaml index b2e663689..2307206bb 100644 --- a/arch/inst/V/vmorn.mm.yaml +++ b/arch/inst/V/vmorn.mm.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmorn.mm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0111001----------010-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmorn.mm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0111001----------010-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vmsbc.vv.yaml b/arch/inst/V/vmsbc.vv.yaml index b1754abb2..b0e07e910 100644 --- a/arch/inst/V/vmsbc.vv.yaml +++ b/arch/inst/V/vmsbc.vv.yaml @@ -1,63 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsbc.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0100111----------000-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsbc.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0100111----------000-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VVMC_VMADC => unsigned(vs2_val[i]) + unsigned(vs1_val[i]) > 2 ^ SEW - 1, - VVMC_VMSBC => unsigned(vs2_val[i]) - unsigned(vs1_val[i]) < 0 - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VVMC_VMADC => unsigned(vs2_val[i]) + unsigned(vs1_val[i]) > 2 ^ SEW - 1, + VVMC_VMSBC => unsigned(vs2_val[i]) - unsigned(vs1_val[i]) < 0 + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsbc.vvm.yaml b/arch/inst/V/vmsbc.vvm.yaml index 4184b967b..af3db9f4f 100644 --- a/arch/inst/V/vmsbc.vvm.yaml +++ b/arch/inst/V/vmsbc.vvm.yaml @@ -1,64 +1,65 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsbc.vvm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0100110----------000-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsbc.vvm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0100110----------000-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VVM_VMADC => unsigned(vs2_val[i]) + unsigned(vs1_val[i]) + unsigned(bool_to_bits(vm_val[i])) > 2 ^ SEW - 1, - VVM_VMSBC => unsigned(vs2_val[i]) - unsigned(vs1_val[i]) - unsigned(bool_to_bits(vm_val[i])) < 0 - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VVM_VMADC => unsigned(vs2_val[i]) + unsigned(vs1_val[i]) + unsigned(bool_to_bits(vm_val[i])) > 2 ^ SEW - 1, + VVM_VMSBC => unsigned(vs2_val[i]) - unsigned(vs1_val[i]) - unsigned(bool_to_bits(vm_val[i])) < 0 + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsbc.vx.yaml b/arch/inst/V/vmsbc.vx.yaml index 6a1e1dd54..3179ccd99 100644 --- a/arch/inst/V/vmsbc.vx.yaml +++ b/arch/inst/V/vmsbc.vx.yaml @@ -1,63 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsbc.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, xs1, vd - encoding: - match: 0100111----------100-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsbc.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, xs1, vd +encoding: + match: 0100111----------100-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VXMC_VMADC => unsigned(vs2_val[i]) + unsigned(rs1_val) > 2 ^ SEW - 1, - VXMC_VMSBC => unsigned(vs2_val[i]) - unsigned(rs1_val) < 0 - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VXMC_VMADC => unsigned(vs2_val[i]) + unsigned(rs1_val) > 2 ^ SEW - 1, + VXMC_VMSBC => unsigned(vs2_val[i]) - unsigned(rs1_val) < 0 + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsbc.vxm.yaml b/arch/inst/V/vmsbc.vxm.yaml index e8c4aeee0..2e54d64e2 100644 --- a/arch/inst/V/vmsbc.vxm.yaml +++ b/arch/inst/V/vmsbc.vxm.yaml @@ -1,64 +1,65 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsbc.vxm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, xs1, vd - encoding: - match: 0100110----------100-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsbc.vxm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, xs1, vd +encoding: + match: 0100110----------100-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VXM_VMADC => unsigned(vs2_val[i]) + unsigned(rs1_val) + unsigned(bool_to_bits(vm_val[i])) > 2 ^ SEW - 1, - VXM_VMSBC => unsigned(vs2_val[i]) - unsigned(rs1_val) - unsigned(bool_to_bits(vm_val[i])) < 0 - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, LMUL_pow, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VXM_VMADC => unsigned(vs2_val[i]) + unsigned(rs1_val) + unsigned(bool_to_bits(vm_val[i])) > 2 ^ SEW - 1, + VXM_VMSBC => unsigned(vs2_val[i]) - unsigned(rs1_val) - unsigned(bool_to_bits(vm_val[i])) < 0 + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsbf.m.yaml b/arch/inst/V/vmsbf.m.yaml index ec15c3a71..bfc1ab0a3 100644 --- a/arch/inst/V/vmsbf.m.yaml +++ b/arch/inst/V/vmsbf.m.yaml @@ -1,62 +1,63 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsbf.m: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010100------00001010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsbf.m +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010100------00001010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = unsigned(vlenb) * 8; - - if illegal_normal(vd, vm) | not(assert_vstart(0)) | vd == vs2 - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, 0, vd_val, vm_val); - - found_elem : bool = false; - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - if vs2_val[i] then found_elem = true; - result[i] = if found_elem then false else true - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = unsigned(vlenb) * 8; - \ No newline at end of file + if illegal_normal(vd, vm) | not(assert_vstart(0)) | vd == vs2 + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, 0, vd_val, vm_val); + + found_elem : bool = false; + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + if vs2_val[i] then found_elem = true; + result[i] = if found_elem then false else true + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmseq.vi.yaml b/arch/inst/V/vmseq.vi.yaml index d59bb33b3..1111623e5 100644 --- a/arch/inst/V/vmseq.vi.yaml +++ b/arch/inst/V/vmseq.vi.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmseq.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 011000-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmseq.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 011000-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VICMP_VMSEQ => vs2_val[i] == imm_val, - VICMP_VMSNE => vs2_val[i] != imm_val, - VICMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(imm_val), - VICMP_VMSLE => signed(vs2_val[i]) <= signed(imm_val), - VICMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(imm_val), - VICMP_VMSGT => signed(vs2_val[i]) > signed(imm_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VICMP_VMSEQ => vs2_val[i] == imm_val, + VICMP_VMSNE => vs2_val[i] != imm_val, + VICMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(imm_val), + VICMP_VMSLE => signed(vs2_val[i]) <= signed(imm_val), + VICMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(imm_val), + VICMP_VMSGT => signed(vs2_val[i]) > signed(imm_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmseq.vv.yaml b/arch/inst/V/vmseq.vv.yaml index 1b32fb961..288533e63 100644 --- a/arch/inst/V/vmseq.vv.yaml +++ b/arch/inst/V/vmseq.vv.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmseq.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 011000-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmseq.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 011000-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VVCMP_VMSEQ => vs2_val[i] == vs1_val[i], - VVCMP_VMSNE => vs2_val[i] != vs1_val[i], - VVCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(vs1_val[i]), - VVCMP_VMSLT => signed(vs2_val[i]) < signed(vs1_val[i]), - VVCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(vs1_val[i]), - VVCMP_VMSLE => signed(vs2_val[i]) <= signed(vs1_val[i]) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VVCMP_VMSEQ => vs2_val[i] == vs1_val[i], + VVCMP_VMSNE => vs2_val[i] != vs1_val[i], + VVCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(vs1_val[i]), + VVCMP_VMSLT => signed(vs2_val[i]) < signed(vs1_val[i]), + VVCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(vs1_val[i]), + VVCMP_VMSLE => signed(vs2_val[i]) <= signed(vs1_val[i]) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmseq.vx.yaml b/arch/inst/V/vmseq.vx.yaml index a12dea1ed..3353ae1f3 100644 --- a/arch/inst/V/vmseq.vx.yaml +++ b/arch/inst/V/vmseq.vx.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmseq.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011000-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmseq.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011000-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VXCMP_VMSEQ => vs2_val[i] == rs1_val, - VXCMP_VMSNE => vs2_val[i] != rs1_val, - VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), - VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), - VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), - VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), - VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), - VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VXCMP_VMSEQ => vs2_val[i] == rs1_val, + VXCMP_VMSNE => vs2_val[i] != rs1_val, + VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), + VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), + VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), + VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), + VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), + VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsgt.vi.yaml b/arch/inst/V/vmsgt.vi.yaml index bee490958..20db0adf9 100644 --- a/arch/inst/V/vmsgt.vi.yaml +++ b/arch/inst/V/vmsgt.vi.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsgt.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 011111-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsgt.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 011111-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VICMP_VMSEQ => vs2_val[i] == imm_val, - VICMP_VMSNE => vs2_val[i] != imm_val, - VICMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(imm_val), - VICMP_VMSLE => signed(vs2_val[i]) <= signed(imm_val), - VICMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(imm_val), - VICMP_VMSGT => signed(vs2_val[i]) > signed(imm_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VICMP_VMSEQ => vs2_val[i] == imm_val, + VICMP_VMSNE => vs2_val[i] != imm_val, + VICMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(imm_val), + VICMP_VMSLE => signed(vs2_val[i]) <= signed(imm_val), + VICMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(imm_val), + VICMP_VMSGT => signed(vs2_val[i]) > signed(imm_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsgt.vx.yaml b/arch/inst/V/vmsgt.vx.yaml index 97162b28d..b7829e81d 100644 --- a/arch/inst/V/vmsgt.vx.yaml +++ b/arch/inst/V/vmsgt.vx.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsgt.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011111-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsgt.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011111-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VXCMP_VMSEQ => vs2_val[i] == rs1_val, - VXCMP_VMSNE => vs2_val[i] != rs1_val, - VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), - VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), - VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), - VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), - VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), - VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VXCMP_VMSEQ => vs2_val[i] == rs1_val, + VXCMP_VMSNE => vs2_val[i] != rs1_val, + VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), + VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), + VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), + VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), + VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), + VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsgtu.vi.yaml b/arch/inst/V/vmsgtu.vi.yaml index 00facedbf..281acc772 100644 --- a/arch/inst/V/vmsgtu.vi.yaml +++ b/arch/inst/V/vmsgtu.vi.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsgtu.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 011110-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsgtu.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 011110-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VICMP_VMSEQ => vs2_val[i] == imm_val, - VICMP_VMSNE => vs2_val[i] != imm_val, - VICMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(imm_val), - VICMP_VMSLE => signed(vs2_val[i]) <= signed(imm_val), - VICMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(imm_val), - VICMP_VMSGT => signed(vs2_val[i]) > signed(imm_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VICMP_VMSEQ => vs2_val[i] == imm_val, + VICMP_VMSNE => vs2_val[i] != imm_val, + VICMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(imm_val), + VICMP_VMSLE => signed(vs2_val[i]) <= signed(imm_val), + VICMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(imm_val), + VICMP_VMSGT => signed(vs2_val[i]) > signed(imm_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsgtu.vx.yaml b/arch/inst/V/vmsgtu.vx.yaml index e60495432..2ea8494fb 100644 --- a/arch/inst/V/vmsgtu.vx.yaml +++ b/arch/inst/V/vmsgtu.vx.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsgtu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011110-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsgtu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011110-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VXCMP_VMSEQ => vs2_val[i] == rs1_val, - VXCMP_VMSNE => vs2_val[i] != rs1_val, - VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), - VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), - VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), - VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), - VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), - VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VXCMP_VMSEQ => vs2_val[i] == rs1_val, + VXCMP_VMSNE => vs2_val[i] != rs1_val, + VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), + VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), + VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), + VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), + VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), + VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsif.m.yaml b/arch/inst/V/vmsif.m.yaml index ab9310303..9b04f46a4 100644 --- a/arch/inst/V/vmsif.m.yaml +++ b/arch/inst/V/vmsif.m.yaml @@ -1,62 +1,63 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsif.m: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010100------00011010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsif.m +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010100------00011010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = unsigned(vlenb) * 8; - - if illegal_normal(vd, vm) | not(assert_vstart(0)) | vd == vs2 - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, 0, vd_val, vm_val); - - found_elem : bool = false; - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = if found_elem then false else true; - if vs2_val[i] then found_elem = true - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = unsigned(vlenb) * 8; - \ No newline at end of file + if illegal_normal(vd, vm) | not(assert_vstart(0)) | vd == vs2 + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, 0, vd_val, vm_val); + + found_elem : bool = false; + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = if found_elem then false else true; + if vs2_val[i] then found_elem = true + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsle.vi.yaml b/arch/inst/V/vmsle.vi.yaml index aba08fed9..2f0fa5a9b 100644 --- a/arch/inst/V/vmsle.vi.yaml +++ b/arch/inst/V/vmsle.vi.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsle.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 011101-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsle.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 011101-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VICMP_VMSEQ => vs2_val[i] == imm_val, - VICMP_VMSNE => vs2_val[i] != imm_val, - VICMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(imm_val), - VICMP_VMSLE => signed(vs2_val[i]) <= signed(imm_val), - VICMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(imm_val), - VICMP_VMSGT => signed(vs2_val[i]) > signed(imm_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VICMP_VMSEQ => vs2_val[i] == imm_val, + VICMP_VMSNE => vs2_val[i] != imm_val, + VICMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(imm_val), + VICMP_VMSLE => signed(vs2_val[i]) <= signed(imm_val), + VICMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(imm_val), + VICMP_VMSGT => signed(vs2_val[i]) > signed(imm_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsle.vv.yaml b/arch/inst/V/vmsle.vv.yaml index fbdfbb98e..12003d18e 100644 --- a/arch/inst/V/vmsle.vv.yaml +++ b/arch/inst/V/vmsle.vv.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsle.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 011101-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsle.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 011101-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VVCMP_VMSEQ => vs2_val[i] == vs1_val[i], - VVCMP_VMSNE => vs2_val[i] != vs1_val[i], - VVCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(vs1_val[i]), - VVCMP_VMSLT => signed(vs2_val[i]) < signed(vs1_val[i]), - VVCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(vs1_val[i]), - VVCMP_VMSLE => signed(vs2_val[i]) <= signed(vs1_val[i]) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VVCMP_VMSEQ => vs2_val[i] == vs1_val[i], + VVCMP_VMSNE => vs2_val[i] != vs1_val[i], + VVCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(vs1_val[i]), + VVCMP_VMSLT => signed(vs2_val[i]) < signed(vs1_val[i]), + VVCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(vs1_val[i]), + VVCMP_VMSLE => signed(vs2_val[i]) <= signed(vs1_val[i]) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsle.vx.yaml b/arch/inst/V/vmsle.vx.yaml index 38cf4c89b..f36e30dfe 100644 --- a/arch/inst/V/vmsle.vx.yaml +++ b/arch/inst/V/vmsle.vx.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsle.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011101-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsle.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011101-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VXCMP_VMSEQ => vs2_val[i] == rs1_val, - VXCMP_VMSNE => vs2_val[i] != rs1_val, - VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), - VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), - VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), - VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), - VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), - VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VXCMP_VMSEQ => vs2_val[i] == rs1_val, + VXCMP_VMSNE => vs2_val[i] != rs1_val, + VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), + VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), + VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), + VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), + VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), + VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsleu.vi.yaml b/arch/inst/V/vmsleu.vi.yaml index 61361314f..568e1c966 100644 --- a/arch/inst/V/vmsleu.vi.yaml +++ b/arch/inst/V/vmsleu.vi.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsleu.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 011100-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsleu.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 011100-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VICMP_VMSEQ => vs2_val[i] == imm_val, - VICMP_VMSNE => vs2_val[i] != imm_val, - VICMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(imm_val), - VICMP_VMSLE => signed(vs2_val[i]) <= signed(imm_val), - VICMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(imm_val), - VICMP_VMSGT => signed(vs2_val[i]) > signed(imm_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VICMP_VMSEQ => vs2_val[i] == imm_val, + VICMP_VMSNE => vs2_val[i] != imm_val, + VICMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(imm_val), + VICMP_VMSLE => signed(vs2_val[i]) <= signed(imm_val), + VICMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(imm_val), + VICMP_VMSGT => signed(vs2_val[i]) > signed(imm_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsleu.vv.yaml b/arch/inst/V/vmsleu.vv.yaml index 81c3ccee2..ce1a24e96 100644 --- a/arch/inst/V/vmsleu.vv.yaml +++ b/arch/inst/V/vmsleu.vv.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsleu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 011100-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsleu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 011100-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VVCMP_VMSEQ => vs2_val[i] == vs1_val[i], - VVCMP_VMSNE => vs2_val[i] != vs1_val[i], - VVCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(vs1_val[i]), - VVCMP_VMSLT => signed(vs2_val[i]) < signed(vs1_val[i]), - VVCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(vs1_val[i]), - VVCMP_VMSLE => signed(vs2_val[i]) <= signed(vs1_val[i]) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VVCMP_VMSEQ => vs2_val[i] == vs1_val[i], + VVCMP_VMSNE => vs2_val[i] != vs1_val[i], + VVCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(vs1_val[i]), + VVCMP_VMSLT => signed(vs2_val[i]) < signed(vs1_val[i]), + VVCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(vs1_val[i]), + VVCMP_VMSLE => signed(vs2_val[i]) <= signed(vs1_val[i]) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsleu.vx.yaml b/arch/inst/V/vmsleu.vx.yaml index 83cb32743..b97fc1f37 100644 --- a/arch/inst/V/vmsleu.vx.yaml +++ b/arch/inst/V/vmsleu.vx.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsleu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011100-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsleu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011100-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VXCMP_VMSEQ => vs2_val[i] == rs1_val, - VXCMP_VMSNE => vs2_val[i] != rs1_val, - VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), - VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), - VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), - VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), - VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), - VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VXCMP_VMSEQ => vs2_val[i] == rs1_val, + VXCMP_VMSNE => vs2_val[i] != rs1_val, + VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), + VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), + VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), + VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), + VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), + VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmslt.vv.yaml b/arch/inst/V/vmslt.vv.yaml index 83549f535..20da4ac03 100644 --- a/arch/inst/V/vmslt.vv.yaml +++ b/arch/inst/V/vmslt.vv.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmslt.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 011011-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmslt.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 011011-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VVCMP_VMSEQ => vs2_val[i] == vs1_val[i], - VVCMP_VMSNE => vs2_val[i] != vs1_val[i], - VVCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(vs1_val[i]), - VVCMP_VMSLT => signed(vs2_val[i]) < signed(vs1_val[i]), - VVCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(vs1_val[i]), - VVCMP_VMSLE => signed(vs2_val[i]) <= signed(vs1_val[i]) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VVCMP_VMSEQ => vs2_val[i] == vs1_val[i], + VVCMP_VMSNE => vs2_val[i] != vs1_val[i], + VVCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(vs1_val[i]), + VVCMP_VMSLT => signed(vs2_val[i]) < signed(vs1_val[i]), + VVCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(vs1_val[i]), + VVCMP_VMSLE => signed(vs2_val[i]) <= signed(vs1_val[i]) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmslt.vx.yaml b/arch/inst/V/vmslt.vx.yaml index cc327acb1..978a9d5e9 100644 --- a/arch/inst/V/vmslt.vx.yaml +++ b/arch/inst/V/vmslt.vx.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmslt.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011011-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmslt.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011011-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VXCMP_VMSEQ => vs2_val[i] == rs1_val, - VXCMP_VMSNE => vs2_val[i] != rs1_val, - VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), - VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), - VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), - VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), - VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), - VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VXCMP_VMSEQ => vs2_val[i] == rs1_val, + VXCMP_VMSNE => vs2_val[i] != rs1_val, + VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), + VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), + VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), + VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), + VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), + VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsltu.vv.yaml b/arch/inst/V/vmsltu.vv.yaml index b55421b2e..99bf21b16 100644 --- a/arch/inst/V/vmsltu.vv.yaml +++ b/arch/inst/V/vmsltu.vv.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsltu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 011010-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsltu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 011010-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VVCMP_VMSEQ => vs2_val[i] == vs1_val[i], - VVCMP_VMSNE => vs2_val[i] != vs1_val[i], - VVCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(vs1_val[i]), - VVCMP_VMSLT => signed(vs2_val[i]) < signed(vs1_val[i]), - VVCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(vs1_val[i]), - VVCMP_VMSLE => signed(vs2_val[i]) <= signed(vs1_val[i]) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VVCMP_VMSEQ => vs2_val[i] == vs1_val[i], + VVCMP_VMSNE => vs2_val[i] != vs1_val[i], + VVCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(vs1_val[i]), + VVCMP_VMSLT => signed(vs2_val[i]) < signed(vs1_val[i]), + VVCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(vs1_val[i]), + VVCMP_VMSLE => signed(vs2_val[i]) <= signed(vs1_val[i]) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsltu.vx.yaml b/arch/inst/V/vmsltu.vx.yaml index fcdf46db3..d6edc3802 100644 --- a/arch/inst/V/vmsltu.vx.yaml +++ b/arch/inst/V/vmsltu.vx.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsltu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011010-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsltu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011010-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VXCMP_VMSEQ => vs2_val[i] == rs1_val, - VXCMP_VMSNE => vs2_val[i] != rs1_val, - VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), - VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), - VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), - VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), - VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), - VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VXCMP_VMSEQ => vs2_val[i] == rs1_val, + VXCMP_VMSNE => vs2_val[i] != rs1_val, + VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), + VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), + VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), + VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), + VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), + VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsne.vi.yaml b/arch/inst/V/vmsne.vi.yaml index d6f0f68bb..fb3913dd4 100644 --- a/arch/inst/V/vmsne.vi.yaml +++ b/arch/inst/V/vmsne.vi.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsne.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 011001-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsne.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 011001-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VICMP_VMSEQ => vs2_val[i] == imm_val, - VICMP_VMSNE => vs2_val[i] != imm_val, - VICMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(imm_val), - VICMP_VMSLE => signed(vs2_val[i]) <= signed(imm_val), - VICMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(imm_val), - VICMP_VMSGT => signed(vs2_val[i]) > signed(imm_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VICMP_VMSEQ => vs2_val[i] == imm_val, + VICMP_VMSNE => vs2_val[i] != imm_val, + VICMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(imm_val), + VICMP_VMSLE => signed(vs2_val[i]) <= signed(imm_val), + VICMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(imm_val), + VICMP_VMSGT => signed(vs2_val[i]) > signed(imm_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsne.vv.yaml b/arch/inst/V/vmsne.vv.yaml index 5b6609cf7..d4155d0fe 100644 --- a/arch/inst/V/vmsne.vv.yaml +++ b/arch/inst/V/vmsne.vv.yaml @@ -1,70 +1,71 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsne.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 011001-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsne.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 011001-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VVCMP_VMSEQ => vs2_val[i] == vs1_val[i], - VVCMP_VMSNE => vs2_val[i] != vs1_val[i], - VVCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(vs1_val[i]), - VVCMP_VMSLT => signed(vs2_val[i]) < signed(vs1_val[i]), - VVCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(vs1_val[i]), - VVCMP_VMSLE => signed(vs2_val[i]) <= signed(vs1_val[i]) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VVCMP_VMSEQ => vs2_val[i] == vs1_val[i], + VVCMP_VMSNE => vs2_val[i] != vs1_val[i], + VVCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(vs1_val[i]), + VVCMP_VMSLT => signed(vs2_val[i]) < signed(vs1_val[i]), + VVCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(vs1_val[i]), + VVCMP_VMSLE => signed(vs2_val[i]) <= signed(vs1_val[i]) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsne.vx.yaml b/arch/inst/V/vmsne.vx.yaml index 06e16bf7f..fabb8489a 100644 --- a/arch/inst/V/vmsne.vx.yaml +++ b/arch/inst/V/vmsne.vx.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsne.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 011001-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsne.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 011001-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let res : bool = match funct6 { - VXCMP_VMSEQ => vs2_val[i] == rs1_val, - VXCMP_VMSNE => vs2_val[i] != rs1_val, - VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), - VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), - VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), - VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), - VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), - VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) - }; - result[i] = res - } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let res : bool = match funct6 { + VXCMP_VMSEQ => vs2_val[i] == rs1_val, + VXCMP_VMSNE => vs2_val[i] != rs1_val, + VXCMP_VMSLTU => unsigned(vs2_val[i]) < unsigned(rs1_val), + VXCMP_VMSLT => signed(vs2_val[i]) < signed(rs1_val), + VXCMP_VMSLEU => unsigned(vs2_val[i]) <= unsigned(rs1_val), + VXCMP_VMSLE => signed(vs2_val[i]) <= signed(rs1_val), + VXCMP_VMSGTU => unsigned(vs2_val[i]) > unsigned(rs1_val), + VXCMP_VMSGT => signed(vs2_val[i]) > signed(rs1_val) + }; + result[i] = res + } + }; + + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmsof.m.yaml b/arch/inst/V/vmsof.m.yaml index a2856b1a4..561216b3c 100644 --- a/arch/inst/V/vmsof.m.yaml +++ b/arch/inst/V/vmsof.m.yaml @@ -1,66 +1,67 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmsof.m: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010100------00010010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmsof.m +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010100------00010010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = unsigned(vlenb) * 8; - - if illegal_normal(vd, vm) | not(assert_vstart(0)) | vd == vs2 - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_cmp(num_elem, SEW, 0, vd_val, vm_val); - - found_elem : bool = false; - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - if vs2_val[i] & not(found_elem) then { - result[i] = true; - found_elem = true - } else { - result[i] = false - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = unsigned(vlenb) * 8; + + if illegal_normal(vd, vm) | not(assert_vstart(0)) | vd == vs2 + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_cmp(num_elem, SEW, 0, vd_val, vm_val); + + found_elem : bool = false; + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + if vs2_val[i] & not(found_elem) then { + result[i] = true; + found_elem = true + } else { + result[i] = false } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmul.vv.yaml b/arch/inst/V/vmul.vv.yaml index 4b3fa3b2f..6de1b16ec 100644 --- a/arch/inst/V/vmul.vv.yaml +++ b/arch/inst/V/vmul.vv.yaml @@ -1,109 +1,110 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmul.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100101-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmul.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100101-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), - MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), - MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VDIVU => { - let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - to_bits(SEW, q) - }, - MVV_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVV_VREMU => { - let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVV_VREM => { - let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), + MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), + MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VDIVU => { + let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + to_bits(SEW, q) + }, + MVV_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVV_VREMU => { + let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVV_VREM => { + let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmul.vx.yaml b/arch/inst/V/vmul.vx.yaml index 3873090bf..f75d0e779 100644 --- a/arch/inst/V/vmul.vx.yaml +++ b/arch/inst/V/vmul.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmul.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100101-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmul.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100101-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmulh.vv.yaml b/arch/inst/V/vmulh.vv.yaml index d87b08e6d..43469bc27 100644 --- a/arch/inst/V/vmulh.vv.yaml +++ b/arch/inst/V/vmulh.vv.yaml @@ -1,109 +1,110 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmulh.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100111-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmulh.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100111-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), - MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), - MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VDIVU => { - let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - to_bits(SEW, q) - }, - MVV_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVV_VREMU => { - let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVV_VREM => { - let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), + MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), + MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VDIVU => { + let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + to_bits(SEW, q) + }, + MVV_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVV_VREMU => { + let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVV_VREM => { + let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmulh.vx.yaml b/arch/inst/V/vmulh.vx.yaml index a17f3505a..36e429154 100644 --- a/arch/inst/V/vmulh.vx.yaml +++ b/arch/inst/V/vmulh.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmulh.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100111-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmulh.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100111-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmulhsu.vv.yaml b/arch/inst/V/vmulhsu.vv.yaml index 711ee2254..0d91b69f6 100644 --- a/arch/inst/V/vmulhsu.vv.yaml +++ b/arch/inst/V/vmulhsu.vv.yaml @@ -1,109 +1,110 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmulhsu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100110-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmulhsu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100110-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), - MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), - MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VDIVU => { - let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - to_bits(SEW, q) - }, - MVV_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVV_VREMU => { - let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVV_VREM => { - let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), + MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), + MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VDIVU => { + let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + to_bits(SEW, q) + }, + MVV_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVV_VREMU => { + let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVV_VREM => { + let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmulhsu.vx.yaml b/arch/inst/V/vmulhsu.vx.yaml index 0b6a12c39..768b155fa 100644 --- a/arch/inst/V/vmulhsu.vx.yaml +++ b/arch/inst/V/vmulhsu.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmulhsu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100110-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmulhsu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100110-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmulhu.vv.yaml b/arch/inst/V/vmulhu.vv.yaml index 37863f11d..8d3dc3204 100644 --- a/arch/inst/V/vmulhu.vv.yaml +++ b/arch/inst/V/vmulhu.vv.yaml @@ -1,109 +1,110 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmulhu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100100-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmulhu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100100-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), - MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), - MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VDIVU => { - let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - to_bits(SEW, q) - }, - MVV_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVV_VREMU => { - let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVV_VREM => { - let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), + MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), + MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VDIVU => { + let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + to_bits(SEW, q) + }, + MVV_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVV_VREMU => { + let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVV_VREM => { + let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmulhu.vx.yaml b/arch/inst/V/vmulhu.vx.yaml index aa3469a8f..baa34f7ef 100644 --- a/arch/inst/V/vmulhu.vx.yaml +++ b/arch/inst/V/vmulhu.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmulhu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100100-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmulhu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100100-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmv.s.x.yaml b/arch/inst/V/vmv.s.x.yaml index 61d3d121a..bbe68c70a 100644 --- a/arch/inst/V/vmv.s.x.yaml +++ b/arch/inst/V/vmv.s.x.yaml @@ -1,63 +1,64 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmv.s.x: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 010000100000-----110-----1010111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmv.s.x +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 010000100000-----110-----1010111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let num_elem = get_num_elem(0, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - assert(num_elem > 0); - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, 'm); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, 0, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, 0, vd_val, vm_val); - - /* one body element */ - if mask[0] then result[0] = rs1_val; - - /* others treated as tail elements */ - let tail_ag : agtype = get_vtype_vta(); - foreach (i from 1 to (num_elem - 1)) { - result[i] = match tail_ag { - UNDISTURBED => vd_val[i], - AGNOSTIC => vd_val[i] /* TODO: configuration support */ - } - }; - - write_vreg(num_elem, SEW, 0, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let num_elem = get_num_elem(0, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + assert(num_elem > 0); + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, 'm); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, 0, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, 0, vd_val, vm_val); + + /* one body element */ + if mask[0] then result[0] = rs1_val; + + /* others treated as tail elements */ + let tail_ag : agtype = get_vtype_vta(); + foreach (i from 1 to (num_elem - 1)) { + result[i] = match tail_ag { + UNDISTURBED => vd_val[i], + AGNOSTIC => vd_val[i] /* TODO: configuration support */ + } + }; + + write_vreg(num_elem, SEW, 0, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmv.v.i.yaml b/arch/inst/V/vmv.v.i.yaml index 723ff5113..6a4f451d8 100644 --- a/arch/inst/V/vmv.v.i.yaml +++ b/arch/inst/V/vmv.v.i.yaml @@ -1,55 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmv.v.i: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vd, imm - encoding: - match: 010111100000-----011-----1010111 - variables: - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmv.v.i +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vd, imm +encoding: + match: 010111100000-----011-----1010111 + variables: + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then result[i] = imm_val - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then result[i] = imm_val + }; + + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmv.v.v.yaml b/arch/inst/V/vmv.v.v.yaml index 61d9db630..477036e39 100644 --- a/arch/inst/V/vmv.v.v.yaml +++ b/arch/inst/V/vmv.v.v.yaml @@ -1,55 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmv.v.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs1, vd - encoding: - match: 010111100000-----000-----1010111 - variables: - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmv.v.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs1, vd +encoding: + match: 010111100000-----000-----1010111 + variables: + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then result[i] = vs1_val[i] - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then result[i] = vs1_val[i] + }; + + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmv.v.x.yaml b/arch/inst/V/vmv.v.x.yaml index 5f052814a..0375fa96d 100644 --- a/arch/inst/V/vmv.v.x.yaml +++ b/arch/inst/V/vmv.v.x.yaml @@ -1,55 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmv.v.x: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vd - encoding: - match: 010111100000-----100-----1010111 - variables: - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmv.v.x +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vd +encoding: + match: 010111100000-----100-----1010111 + variables: + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let rs1_val : bits('m) = get_scalar(rs1, 'm); - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then result[i] = rs1_val - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let rs1_val : bits('m) = get_scalar(rs1, 'm); + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then result[i] = rs1_val + }; + + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmv.x.s.yaml b/arch/inst/V/vmv.x.s.yaml index 1fa4cc26b..0c126cbb3 100644 --- a/arch/inst/V/vmv.x.s.yaml +++ b/arch/inst/V/vmv.x.s.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmv.x.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, xd - encoding: - match: 0100001-----00000010-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmv.x.s +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, xd +encoding: + match: 0100001-----00000010-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let num_elem = get_num_elem(0, SEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - assert(num_elem > 0); - let 'n = num_elem; - let 'm = SEW; - - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, 0, vs2); - X(rd) = if sizeof(xlen) < SEW then slice(vs2_val[0], 0, sizeof(xlen)) - else if sizeof(xlen) > SEW then sign_extend(vs2_val[0]) - else vs2_val[0]; - vstart = zeros(); - - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let num_elem = get_num_elem(0, SEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + assert(num_elem > 0); + let 'n = num_elem; + let 'm = SEW; + + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, 0, vs2); + X(rd) = if sizeof(xlen) < SEW then slice(vs2_val[0], 0, sizeof(xlen)) + else if sizeof(xlen) > SEW then sign_extend(vs2_val[0]) + else vs2_val[0]; + vstart = zeros(); + + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmv1r.v.yaml b/arch/inst/V/vmv1r.v.yaml index a74368bae..1a059cec6 100644 --- a/arch/inst/V/vmv1r.v.yaml +++ b/arch/inst/V/vmv1r.v.yaml @@ -1,55 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmv1r.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vd - encoding: - match: 1001111-----00000011-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmv1r.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vd +encoding: + match: 1001111-----00000011-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let start_element = get_start_element(); - let SEW = get_sew(); - let imm_val = unsigned(zero_extend(sizeof(xlen), simm)); - let EMUL = imm_val + 1; - - if not(EMUL == 1 | EMUL == 2 | EMUL == 4 | EMUL == 8) then { handle_illegal(); return RETIRE_FAIL }; - - let EMUL_pow = log2(EMUL); - let num_elem = get_num_elem(EMUL_pow, SEW); - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - - foreach (i from 0 to (num_elem - 1)) { - result[i] = if i < start_element then vd_val[i] else vs2_val[i] - }; - - write_vreg(num_elem, SEW, EMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let start_element = get_start_element(); + let SEW = get_sew(); + let imm_val = unsigned(zero_extend(sizeof(xlen), simm)); + let EMUL = imm_val + 1; - \ No newline at end of file + if not(EMUL == 1 | EMUL == 2 | EMUL == 4 | EMUL == 8) then { handle_illegal(); return RETIRE_FAIL }; + + let EMUL_pow = log2(EMUL); + let num_elem = get_num_elem(EMUL_pow, SEW); + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + + foreach (i from 0 to (num_elem - 1)) { + result[i] = if i < start_element then vd_val[i] else vs2_val[i] + }; + + write_vreg(num_elem, SEW, EMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmv2r.v.yaml b/arch/inst/V/vmv2r.v.yaml index 0d918a83c..0c4b695e8 100644 --- a/arch/inst/V/vmv2r.v.yaml +++ b/arch/inst/V/vmv2r.v.yaml @@ -1,55 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmv2r.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vd - encoding: - match: 1001111-----00001011-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmv2r.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vd +encoding: + match: 1001111-----00001011-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let start_element = get_start_element(); - let SEW = get_sew(); - let imm_val = unsigned(zero_extend(sizeof(xlen), simm)); - let EMUL = imm_val + 1; - - if not(EMUL == 1 | EMUL == 2 | EMUL == 4 | EMUL == 8) then { handle_illegal(); return RETIRE_FAIL }; - - let EMUL_pow = log2(EMUL); - let num_elem = get_num_elem(EMUL_pow, SEW); - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - - foreach (i from 0 to (num_elem - 1)) { - result[i] = if i < start_element then vd_val[i] else vs2_val[i] - }; - - write_vreg(num_elem, SEW, EMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let start_element = get_start_element(); + let SEW = get_sew(); + let imm_val = unsigned(zero_extend(sizeof(xlen), simm)); + let EMUL = imm_val + 1; - \ No newline at end of file + if not(EMUL == 1 | EMUL == 2 | EMUL == 4 | EMUL == 8) then { handle_illegal(); return RETIRE_FAIL }; + + let EMUL_pow = log2(EMUL); + let num_elem = get_num_elem(EMUL_pow, SEW); + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + + foreach (i from 0 to (num_elem - 1)) { + result[i] = if i < start_element then vd_val[i] else vs2_val[i] + }; + + write_vreg(num_elem, SEW, EMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmv4r.v.yaml b/arch/inst/V/vmv4r.v.yaml index 1a8ac2a11..5da446a95 100644 --- a/arch/inst/V/vmv4r.v.yaml +++ b/arch/inst/V/vmv4r.v.yaml @@ -1,55 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmv4r.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vd - encoding: - match: 1001111-----00011011-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmv4r.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vd +encoding: + match: 1001111-----00011011-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let start_element = get_start_element(); - let SEW = get_sew(); - let imm_val = unsigned(zero_extend(sizeof(xlen), simm)); - let EMUL = imm_val + 1; - - if not(EMUL == 1 | EMUL == 2 | EMUL == 4 | EMUL == 8) then { handle_illegal(); return RETIRE_FAIL }; - - let EMUL_pow = log2(EMUL); - let num_elem = get_num_elem(EMUL_pow, SEW); - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - - foreach (i from 0 to (num_elem - 1)) { - result[i] = if i < start_element then vd_val[i] else vs2_val[i] - }; - - write_vreg(num_elem, SEW, EMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let start_element = get_start_element(); + let SEW = get_sew(); + let imm_val = unsigned(zero_extend(sizeof(xlen), simm)); + let EMUL = imm_val + 1; - \ No newline at end of file + if not(EMUL == 1 | EMUL == 2 | EMUL == 4 | EMUL == 8) then { handle_illegal(); return RETIRE_FAIL }; + + let EMUL_pow = log2(EMUL); + let num_elem = get_num_elem(EMUL_pow, SEW); + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + + foreach (i from 0 to (num_elem - 1)) { + result[i] = if i < start_element then vd_val[i] else vs2_val[i] + }; + + write_vreg(num_elem, SEW, EMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmv8r.v.yaml b/arch/inst/V/vmv8r.v.yaml index 842f70850..1154eb63e 100644 --- a/arch/inst/V/vmv8r.v.yaml +++ b/arch/inst/V/vmv8r.v.yaml @@ -1,55 +1,56 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmv8r.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vd - encoding: - match: 1001111-----00111011-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmv8r.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vd +encoding: + match: 1001111-----00111011-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let start_element = get_start_element(); - let SEW = get_sew(); - let imm_val = unsigned(zero_extend(sizeof(xlen), simm)); - let EMUL = imm_val + 1; - - if not(EMUL == 1 | EMUL == 2 | EMUL == 4 | EMUL == 8) then { handle_illegal(); return RETIRE_FAIL }; - - let EMUL_pow = log2(EMUL); - let num_elem = get_num_elem(EMUL_pow, SEW); - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - - foreach (i from 0 to (num_elem - 1)) { - result[i] = if i < start_element then vd_val[i] else vs2_val[i] - }; - - write_vreg(num_elem, SEW, EMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let start_element = get_start_element(); + let SEW = get_sew(); + let imm_val = unsigned(zero_extend(sizeof(xlen), simm)); + let EMUL = imm_val + 1; - \ No newline at end of file + if not(EMUL == 1 | EMUL == 2 | EMUL == 4 | EMUL == 8) then { handle_illegal(); return RETIRE_FAIL }; + + let EMUL_pow = log2(EMUL); + let num_elem = get_num_elem(EMUL_pow, SEW); + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, 0b1, 0b00000); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, EMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + + foreach (i from 0 to (num_elem - 1)) { + result[i] = if i < start_element then vd_val[i] else vs2_val[i] + }; + + write_vreg(num_elem, SEW, EMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmxnor.mm.yaml b/arch/inst/V/vmxnor.mm.yaml index 277019b7f..9701400e8 100644 --- a/arch/inst/V/vmxnor.mm.yaml +++ b/arch/inst/V/vmxnor.mm.yaml @@ -1,68 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmxnor.mm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0111111----------010-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmxnor.mm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0111111----------010-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = unsigned(vlenb) * 8; - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); - let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, 0, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MM_VMAND => vs2_val[i] & vs1_val[i], - MM_VMNAND => not(vs2_val[i] & vs1_val[i]), - MM_VMANDNOT => vs2_val[i] & not(vs1_val[i]), - MM_VMXOR => vs2_val[i] != vs1_val[i], - MM_VMOR => vs2_val[i] | vs1_val[i], - MM_VMNOR => not(vs2_val[i] | vs1_val[i]), - MM_VMORNOT => vs2_val[i] | not(vs1_val[i]), - MM_VMXNOR => vs2_val[i] == vs1_val[i] - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = unsigned(vlenb) * 8; + + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); + let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, 0, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MM_VMAND => vs2_val[i] & vs1_val[i], + MM_VMNAND => not(vs2_val[i] & vs1_val[i]), + MM_VMANDNOT => vs2_val[i] & not(vs1_val[i]), + MM_VMXOR => vs2_val[i] != vs1_val[i], + MM_VMOR => vs2_val[i] | vs1_val[i], + MM_VMNOR => not(vs2_val[i] | vs1_val[i]), + MM_VMORNOT => vs2_val[i] | not(vs1_val[i]), + MM_VMXNOR => vs2_val[i] == vs1_val[i] } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vmxor.mm.yaml b/arch/inst/V/vmxor.mm.yaml index 61a2fbdbc..1f65ed0e3 100644 --- a/arch/inst/V/vmxor.mm.yaml +++ b/arch/inst/V/vmxor.mm.yaml @@ -1,68 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vmxor.mm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0110111----------010-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vmxor.mm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0110111----------010-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = unsigned(vlenb) * 8; - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); - let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); - let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); - result : vector('n, dec, bool) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result_carry(num_elem, SEW, 0, vd_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MM_VMAND => vs2_val[i] & vs1_val[i], - MM_VMNAND => not(vs2_val[i] & vs1_val[i]), - MM_VMANDNOT => vs2_val[i] & not(vs1_val[i]), - MM_VMXOR => vs2_val[i] != vs1_val[i], - MM_VMOR => vs2_val[i] | vs1_val[i], - MM_VMNOR => not(vs2_val[i] | vs1_val[i]), - MM_VMORNOT => vs2_val[i] | not(vs1_val[i]), - MM_VMXNOR => vs2_val[i] == vs1_val[i] - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = unsigned(vlenb) * 8; + + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vs1_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs1); + let vs2_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vs2); + let vd_val : vector('n, dec, bool) = read_vmask(num_elem, 0b0, vd); + result : vector('n, dec, bool) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result_carry(num_elem, SEW, 0, vd_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MM_VMAND => vs2_val[i] & vs1_val[i], + MM_VMNAND => not(vs2_val[i] & vs1_val[i]), + MM_VMANDNOT => vs2_val[i] & not(vs1_val[i]), + MM_VMXOR => vs2_val[i] != vs1_val[i], + MM_VMOR => vs2_val[i] | vs1_val[i], + MM_VMNOR => not(vs2_val[i] | vs1_val[i]), + MM_VMORNOT => vs2_val[i] | not(vs1_val[i]), + MM_VMXNOR => vs2_val[i] == vs1_val[i] } - }; - - write_vmask(num_elem, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vmask(num_elem, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnclip.wi.yaml b/arch/inst/V/vnclip.wi.yaml index 6aa71810d..ffdc9e4dc 100644 --- a/arch/inst/V/vnclip.wi.yaml +++ b/arch/inst/V/vnclip.wi.yaml @@ -1,80 +1,81 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnclip.wi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 101111-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnclip.wi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 101111-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW_widen <= 64); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let shift_amount = get_shift_amount(imm_val, SEW_widen); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - result[i] = match funct6 { - NI_VNCLIPU => { - let result_wide = (vs2_val[i] >> shift_amount) + zero_extend('o, rounding_incr); - unsigned_saturation('m, result_wide) - }, - NI_VNCLIP => { - let v_double : bits('m * 4) = sign_extend(vs2_val[i]); - let result_wide = slice(v_double >> shift_amount, 0, 'o) + zero_extend('o, rounding_incr); - signed_saturation('m, result_wide) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW_widen <= 64); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let shift_amount = get_shift_amount(imm_val, SEW_widen); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + result[i] = match funct6 { + NI_VNCLIPU => { + let result_wide = (vs2_val[i] >> shift_amount) + zero_extend('o, rounding_incr); + unsigned_saturation('m, result_wide) + }, + NI_VNCLIP => { + let v_double : bits('m * 4) = sign_extend(vs2_val[i]); + let result_wide = slice(v_double >> shift_amount, 0, 'o) + zero_extend('o, rounding_incr); + signed_saturation('m, result_wide) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnclip.wv.yaml b/arch/inst/V/vnclip.wv.yaml index 57e4903be..29112c838 100644 --- a/arch/inst/V/vnclip.wv.yaml +++ b/arch/inst/V/vnclip.wv.yaml @@ -1,80 +1,81 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnclip.wv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101111-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnclip.wv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101111-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW_widen <= 64); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let shift_amount = get_shift_amount(vs1_val[i], SEW_widen); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - result[i] = match funct6 { - NV_VNCLIPU => { - let result_wide = (vs2_val[i] >> shift_amount) + zero_extend('o, rounding_incr); - unsigned_saturation('m, result_wide); - }, - NV_VNCLIP => { - let v_double : bits('m * 4) = sign_extend(vs2_val[i]); - let result_wide = slice(v_double >> shift_amount, 0, 'o) + zero_extend('o, rounding_incr); - signed_saturation('m, result_wide); - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW_widen <= 64); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let shift_amount = get_shift_amount(vs1_val[i], SEW_widen); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + result[i] = match funct6 { + NV_VNCLIPU => { + let result_wide = (vs2_val[i] >> shift_amount) + zero_extend('o, rounding_incr); + unsigned_saturation('m, result_wide); + }, + NV_VNCLIP => { + let v_double : bits('m * 4) = sign_extend(vs2_val[i]); + let result_wide = slice(v_double >> shift_amount, 0, 'o) + zero_extend('o, rounding_incr); + signed_saturation('m, result_wide); + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnclip.wx.yaml b/arch/inst/V/vnclip.wx.yaml index 0f7d96d00..adf57842d 100644 --- a/arch/inst/V/vnclip.wx.yaml +++ b/arch/inst/V/vnclip.wx.yaml @@ -1,80 +1,81 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnclip.wx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101111-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnclip.wx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101111-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW_widen <= 64); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let shift_amount = get_shift_amount(rs1_val, SEW_widen); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - result[i] = match funct6 { - NX_VNCLIPU => { - let result_wide = (vs2_val[i] >> shift_amount) + zero_extend('o, rounding_incr); - unsigned_saturation('m, result_wide) - }, - NX_VNCLIP => { - let v_double : bits('m * 4) = sign_extend(vs2_val[i]); - let result_wide = slice(v_double >> shift_amount, 0, 'o) + zero_extend('o, rounding_incr); - signed_saturation('m, result_wide) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW_widen <= 64); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let shift_amount = get_shift_amount(rs1_val, SEW_widen); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + result[i] = match funct6 { + NX_VNCLIPU => { + let result_wide = (vs2_val[i] >> shift_amount) + zero_extend('o, rounding_incr); + unsigned_saturation('m, result_wide) + }, + NX_VNCLIP => { + let v_double : bits('m * 4) = sign_extend(vs2_val[i]); + let result_wide = slice(v_double >> shift_amount, 0, 'o) + zero_extend('o, rounding_incr); + signed_saturation('m, result_wide) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnclipu.wi.yaml b/arch/inst/V/vnclipu.wi.yaml index 383cdcda4..9d2789f0b 100644 --- a/arch/inst/V/vnclipu.wi.yaml +++ b/arch/inst/V/vnclipu.wi.yaml @@ -1,80 +1,81 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnclipu.wi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 101110-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnclipu.wi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 101110-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW_widen <= 64); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let shift_amount = get_shift_amount(imm_val, SEW_widen); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - result[i] = match funct6 { - NI_VNCLIPU => { - let result_wide = (vs2_val[i] >> shift_amount) + zero_extend('o, rounding_incr); - unsigned_saturation('m, result_wide) - }, - NI_VNCLIP => { - let v_double : bits('m * 4) = sign_extend(vs2_val[i]); - let result_wide = slice(v_double >> shift_amount, 0, 'o) + zero_extend('o, rounding_incr); - signed_saturation('m, result_wide) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW_widen <= 64); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let shift_amount = get_shift_amount(imm_val, SEW_widen); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + result[i] = match funct6 { + NI_VNCLIPU => { + let result_wide = (vs2_val[i] >> shift_amount) + zero_extend('o, rounding_incr); + unsigned_saturation('m, result_wide) + }, + NI_VNCLIP => { + let v_double : bits('m * 4) = sign_extend(vs2_val[i]); + let result_wide = slice(v_double >> shift_amount, 0, 'o) + zero_extend('o, rounding_incr); + signed_saturation('m, result_wide) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnclipu.wv.yaml b/arch/inst/V/vnclipu.wv.yaml index 2dd7ca37a..075172d52 100644 --- a/arch/inst/V/vnclipu.wv.yaml +++ b/arch/inst/V/vnclipu.wv.yaml @@ -1,80 +1,81 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnclipu.wv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101110-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnclipu.wv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101110-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW_widen <= 64); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let shift_amount = get_shift_amount(vs1_val[i], SEW_widen); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - result[i] = match funct6 { - NV_VNCLIPU => { - let result_wide = (vs2_val[i] >> shift_amount) + zero_extend('o, rounding_incr); - unsigned_saturation('m, result_wide); - }, - NV_VNCLIP => { - let v_double : bits('m * 4) = sign_extend(vs2_val[i]); - let result_wide = slice(v_double >> shift_amount, 0, 'o) + zero_extend('o, rounding_incr); - signed_saturation('m, result_wide); - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW_widen <= 64); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let shift_amount = get_shift_amount(vs1_val[i], SEW_widen); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + result[i] = match funct6 { + NV_VNCLIPU => { + let result_wide = (vs2_val[i] >> shift_amount) + zero_extend('o, rounding_incr); + unsigned_saturation('m, result_wide); + }, + NV_VNCLIP => { + let v_double : bits('m * 4) = sign_extend(vs2_val[i]); + let result_wide = slice(v_double >> shift_amount, 0, 'o) + zero_extend('o, rounding_incr); + signed_saturation('m, result_wide); + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnclipu.wx.yaml b/arch/inst/V/vnclipu.wx.yaml index 663fcb09f..3e102c019 100644 --- a/arch/inst/V/vnclipu.wx.yaml +++ b/arch/inst/V/vnclipu.wx.yaml @@ -1,80 +1,81 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnclipu.wx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101110-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnclipu.wx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101110-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW_widen <= 64); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - let shift_amount = get_shift_amount(rs1_val, SEW_widen); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - result[i] = match funct6 { - NX_VNCLIPU => { - let result_wide = (vs2_val[i] >> shift_amount) + zero_extend('o, rounding_incr); - unsigned_saturation('m, result_wide) - }, - NX_VNCLIP => { - let v_double : bits('m * 4) = sign_extend(vs2_val[i]); - let result_wide = slice(v_double >> shift_amount, 0, 'o) + zero_extend('o, rounding_incr); - signed_saturation('m, result_wide) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW_widen <= 64); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + let shift_amount = get_shift_amount(rs1_val, SEW_widen); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + result[i] = match funct6 { + NX_VNCLIPU => { + let result_wide = (vs2_val[i] >> shift_amount) + zero_extend('o, rounding_incr); + unsigned_saturation('m, result_wide) + }, + NX_VNCLIP => { + let v_double : bits('m * 4) = sign_extend(vs2_val[i]); + let result_wide = slice(v_double >> shift_amount, 0, 'o) + zero_extend('o, rounding_incr); + signed_saturation('m, result_wide) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnmsac.vv.yaml b/arch/inst/V/vnmsac.vv.yaml index 7b0fea34a..8489b01a0 100644 --- a/arch/inst/V/vnmsac.vv.yaml +++ b/arch/inst/V/vnmsac.vv.yaml @@ -1,67 +1,68 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnmsac.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101111-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnmsac.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101111-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VMACC => get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0) + vd_val[i], - MVV_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0), - MVV_VMADD => get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) + vs2_val[i], - MVV_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VMACC => get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0) + vd_val[i], + MVV_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0), + MVV_VMADD => get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) + vs2_val[i], + MVV_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnmsac.vx.yaml b/arch/inst/V/vnmsac.vx.yaml index 54eeead20..dcd3e2aa2 100644 --- a/arch/inst/V/vnmsac.vx.yaml +++ b/arch/inst/V/vnmsac.vx.yaml @@ -1,67 +1,68 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnmsac.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101111-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnmsac.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101111-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VMACC => get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0) + vd_val[i], - MVX_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0), - MVX_VMADD => get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) + vs2_val[i], - MVX_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VMACC => get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0) + vd_val[i], + MVX_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0), + MVX_VMADD => get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) + vs2_val[i], + MVX_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnmsub.vv.yaml b/arch/inst/V/vnmsub.vv.yaml index 53f280b46..9b34de28d 100644 --- a/arch/inst/V/vnmsub.vv.yaml +++ b/arch/inst/V/vnmsub.vv.yaml @@ -1,67 +1,68 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnmsub.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101011-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnmsub.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101011-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VMACC => get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0) + vd_val[i], - MVV_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0), - MVV_VMADD => get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) + vs2_val[i], - MVV_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VMACC => get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0) + vd_val[i], + MVV_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vs2_val[i]), 0), + MVV_VMADD => get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) + vs2_val[i], + MVV_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(vs1_val[i]) * signed(vd_val[i]), 0) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnmsub.vx.yaml b/arch/inst/V/vnmsub.vx.yaml index 927704a03..9e1b63f0f 100644 --- a/arch/inst/V/vnmsub.vx.yaml +++ b/arch/inst/V/vnmsub.vx.yaml @@ -1,67 +1,68 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnmsub.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101011-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnmsub.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101011-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VMACC => get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0) + vd_val[i], - MVX_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0), - MVX_VMADD => get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) + vs2_val[i], - MVX_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VMACC => get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0) + vd_val[i], + MVX_VNMSAC => vd_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vs2_val[i]), 0), + MVX_VMADD => get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) + vs2_val[i], + MVX_VNMSUB => vs2_val[i] - get_slice_int(SEW, signed(rs1_val) * signed(vd_val[i]), 0) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnsra.wi.yaml b/arch/inst/V/vnsra.wi.yaml index 9e7627cf1..bc8a52603 100644 --- a/arch/inst/V/vnsra.wi.yaml +++ b/arch/inst/V/vnsra.wi.yaml @@ -1,79 +1,80 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnsra.wi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 101101-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnsra.wi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 101101-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW_widen <= 64); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - NIS_VNSRL => { - let shift_amount = get_shift_amount(imm_val, SEW_widen); - slice(vs2_val[i] >> shift_amount, 0, SEW) - }, - NIS_VNSRA => { - let shift_amount = get_shift_amount(imm_val, SEW_widen); - let v_double : bits('o * 2) = sign_extend(vs2_val[i]); - let arith_shifted : bits('o) = slice(v_double >> shift_amount, 0, SEW_widen); - slice(arith_shifted, 0, SEW) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW_widen <= 64); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + NIS_VNSRL => { + let shift_amount = get_shift_amount(imm_val, SEW_widen); + slice(vs2_val[i] >> shift_amount, 0, SEW) + }, + NIS_VNSRA => { + let shift_amount = get_shift_amount(imm_val, SEW_widen); + let v_double : bits('o * 2) = sign_extend(vs2_val[i]); + let arith_shifted : bits('o) = slice(v_double >> shift_amount, 0, SEW_widen); + slice(arith_shifted, 0, SEW) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnsra.wv.yaml b/arch/inst/V/vnsra.wv.yaml index e51d5c171..678d1b379 100644 --- a/arch/inst/V/vnsra.wv.yaml +++ b/arch/inst/V/vnsra.wv.yaml @@ -1,79 +1,80 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnsra.wv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101101-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnsra.wv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101101-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW_widen <= 64); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - NVS_VNSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW_widen); - slice(vs2_val[i] >> shift_amount, 0, SEW) - }, - NVS_VNSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW_widen); - let v_double : bits('o * 2) = sign_extend(vs2_val[i]); - let arith_shifted : bits('o) = slice(v_double >> shift_amount, 0, SEW_widen); - slice(arith_shifted, 0, SEW) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW_widen <= 64); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + NVS_VNSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW_widen); + slice(vs2_val[i] >> shift_amount, 0, SEW) + }, + NVS_VNSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW_widen); + let v_double : bits('o * 2) = sign_extend(vs2_val[i]); + let arith_shifted : bits('o) = slice(v_double >> shift_amount, 0, SEW_widen); + slice(arith_shifted, 0, SEW) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnsra.wx.yaml b/arch/inst/V/vnsra.wx.yaml index 4c36210f9..61bbe59f2 100644 --- a/arch/inst/V/vnsra.wx.yaml +++ b/arch/inst/V/vnsra.wx.yaml @@ -1,79 +1,80 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnsra.wx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101101-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnsra.wx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101101-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW_widen <= 64); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - NXS_VNSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW_widen); - slice(vs2_val[i] >> shift_amount, 0, SEW) - }, - NXS_VNSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW_widen); - let v_double : bits('o * 2) = sign_extend(vs2_val[i]); - let arith_shifted : bits('o) = slice(v_double >> shift_amount, 0, SEW_widen); - slice(arith_shifted, 0, SEW) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW_widen <= 64); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + NXS_VNSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW_widen); + slice(vs2_val[i] >> shift_amount, 0, SEW) + }, + NXS_VNSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW_widen); + let v_double : bits('o * 2) = sign_extend(vs2_val[i]); + let arith_shifted : bits('o) = slice(v_double >> shift_amount, 0, SEW_widen); + slice(arith_shifted, 0, SEW) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnsrl.wi.yaml b/arch/inst/V/vnsrl.wi.yaml index 0b064e18e..7ab138f44 100644 --- a/arch/inst/V/vnsrl.wi.yaml +++ b/arch/inst/V/vnsrl.wi.yaml @@ -1,79 +1,80 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnsrl.wi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 101100-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnsrl.wi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 101100-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW_widen <= 64); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - NIS_VNSRL => { - let shift_amount = get_shift_amount(imm_val, SEW_widen); - slice(vs2_val[i] >> shift_amount, 0, SEW) - }, - NIS_VNSRA => { - let shift_amount = get_shift_amount(imm_val, SEW_widen); - let v_double : bits('o * 2) = sign_extend(vs2_val[i]); - let arith_shifted : bits('o) = slice(v_double >> shift_amount, 0, SEW_widen); - slice(arith_shifted, 0, SEW) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW_widen <= 64); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + NIS_VNSRL => { + let shift_amount = get_shift_amount(imm_val, SEW_widen); + slice(vs2_val[i] >> shift_amount, 0, SEW) + }, + NIS_VNSRA => { + let shift_amount = get_shift_amount(imm_val, SEW_widen); + let v_double : bits('o * 2) = sign_extend(vs2_val[i]); + let arith_shifted : bits('o) = slice(v_double >> shift_amount, 0, SEW_widen); + slice(arith_shifted, 0, SEW) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnsrl.wv.yaml b/arch/inst/V/vnsrl.wv.yaml index a2fe0f678..4629cfa96 100644 --- a/arch/inst/V/vnsrl.wv.yaml +++ b/arch/inst/V/vnsrl.wv.yaml @@ -1,79 +1,80 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnsrl.wv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101100-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnsrl.wv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101100-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW_widen <= 64); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - NVS_VNSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW_widen); - slice(vs2_val[i] >> shift_amount, 0, SEW) - }, - NVS_VNSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW_widen); - let v_double : bits('o * 2) = sign_extend(vs2_val[i]); - let arith_shifted : bits('o) = slice(v_double >> shift_amount, 0, SEW_widen); - slice(arith_shifted, 0, SEW) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW_widen <= 64); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + NVS_VNSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW_widen); + slice(vs2_val[i] >> shift_amount, 0, SEW) + }, + NVS_VNSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW_widen); + let v_double : bits('o * 2) = sign_extend(vs2_val[i]); + let arith_shifted : bits('o) = slice(v_double >> shift_amount, 0, SEW_widen); + slice(arith_shifted, 0, SEW) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vnsrl.wx.yaml b/arch/inst/V/vnsrl.wx.yaml index 77705fadd..0ece78c6d 100644 --- a/arch/inst/V/vnsrl.wx.yaml +++ b/arch/inst/V/vnsrl.wx.yaml @@ -1,79 +1,80 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vnsrl.wx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101100-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vnsrl.wx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101100-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW_widen <= 64); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - NXS_VNSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW_widen); - slice(vs2_val[i] >> shift_amount, 0, SEW) - }, - NXS_VNSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW_widen); - let v_double : bits('o * 2) = sign_extend(vs2_val[i]); - let arith_shifted : bits('o) = slice(v_double >> shift_amount, 0, SEW_widen); - slice(arith_shifted, 0, SEW) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_widen, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW_widen <= 64); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + NXS_VNSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW_widen); + slice(vs2_val[i] >> shift_amount, 0, SEW) + }, + NXS_VNSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW_widen); + let v_double : bits('o * 2) = sign_extend(vs2_val[i]); + let arith_shifted : bits('o) = slice(v_double >> shift_amount, 0, SEW_widen); + slice(arith_shifted, 0, SEW) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vor.vi.yaml b/arch/inst/V/vor.vi.yaml index 788df2e01..afccdd98e 100644 --- a/arch/inst/V/vor.vi.yaml +++ b/arch/inst/V/vor.vi.yaml @@ -1,94 +1,95 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vor.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 001010-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vor.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 001010-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VADD => vs2_val[i] + imm_val, - VI_VRSUB => imm_val - vs2_val[i], - VI_VAND => vs2_val[i] & imm_val, - VI_VOR => vs2_val[i] | imm_val, - VI_VXOR => vs2_val[i] ^ imm_val, - VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), - VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), - VI_VSLL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] << shift_amount - }, - VI_VSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] >> shift_amount - }, - VI_VSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VI_VSSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VI_VSSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VADD => vs2_val[i] + imm_val, + VI_VRSUB => imm_val - vs2_val[i], + VI_VAND => vs2_val[i] & imm_val, + VI_VOR => vs2_val[i] | imm_val, + VI_VXOR => vs2_val[i] ^ imm_val, + VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), + VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), + VI_VSLL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] << shift_amount + }, + VI_VSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] >> shift_amount + }, + VI_VSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VI_VSSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VI_VSSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vor.vv.yaml b/arch/inst/V/vor.vv.yaml index 16233ed7e..130894e9b 100644 --- a/arch/inst/V/vor.vv.yaml +++ b/arch/inst/V/vor.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vor.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 001010-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vor.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 001010-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vor.vx.yaml b/arch/inst/V/vor.vx.yaml index d970c818a..b38fe6584 100644 --- a/arch/inst/V/vor.vx.yaml +++ b/arch/inst/V/vor.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vor.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001010-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vor.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001010-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vredand.vs.yaml b/arch/inst/V/vredand.vs.yaml index ec5661567..fa531e5e9 100644 --- a/arch/inst/V/vredand.vs.yaml +++ b/arch/inst/V/vredand.vs.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vredand.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000001-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vredand.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000001-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ - - if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; - - if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ - - let 'n = num_elem_vs; - let 'd = num_elem_vd; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); - let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); - let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); - - sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ - foreach (i from 0 to (num_elem_vs - 1)) { - if mask[i] then { - sum = match funct6 { - MVV_VREDSUM => sum + vs2_val[i], - MVV_VREDAND => sum & vs2_val[i], - MVV_VREDOR => sum | vs2_val[i], - MVV_VREDXOR => sum ^ vs2_val[i], - MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), - MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), - MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), - MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); + let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ + + if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; + + if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ + + let 'n = num_elem_vs; + let 'd = num_elem_vd; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); + let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); + let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); + + sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ + foreach (i from 0 to (num_elem_vs - 1)) { + if mask[i] then { + sum = match funct6 { + MVV_VREDSUM => sum + vs2_val[i], + MVV_VREDAND => sum & vs2_val[i], + MVV_VREDOR => sum | vs2_val[i], + MVV_VREDXOR => sum ^ vs2_val[i], + MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), + MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), + MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), + MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) } - }; - - write_single_element(SEW, 0, vd, sum); - /* other elements in vd are treated as tail elements, currently remain unchanged */ - /* TODO: configuration support for agnostic behavior */ - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_single_element(SEW, 0, vd, sum); + /* other elements in vd are treated as tail elements, currently remain unchanged */ + /* TODO: configuration support for agnostic behavior */ + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vredmax.vs.yaml b/arch/inst/V/vredmax.vs.yaml index a139de505..428f7dc53 100644 --- a/arch/inst/V/vredmax.vs.yaml +++ b/arch/inst/V/vredmax.vs.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vredmax.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000111-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vredmax.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000111-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ - - if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; - - if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ - - let 'n = num_elem_vs; - let 'd = num_elem_vd; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); - let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); - let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); - - sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ - foreach (i from 0 to (num_elem_vs - 1)) { - if mask[i] then { - sum = match funct6 { - MVV_VREDSUM => sum + vs2_val[i], - MVV_VREDAND => sum & vs2_val[i], - MVV_VREDOR => sum | vs2_val[i], - MVV_VREDXOR => sum ^ vs2_val[i], - MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), - MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), - MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), - MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); + let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ + + if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; + + if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ + + let 'n = num_elem_vs; + let 'd = num_elem_vd; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); + let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); + let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); + + sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ + foreach (i from 0 to (num_elem_vs - 1)) { + if mask[i] then { + sum = match funct6 { + MVV_VREDSUM => sum + vs2_val[i], + MVV_VREDAND => sum & vs2_val[i], + MVV_VREDOR => sum | vs2_val[i], + MVV_VREDXOR => sum ^ vs2_val[i], + MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), + MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), + MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), + MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) } - }; - - write_single_element(SEW, 0, vd, sum); - /* other elements in vd are treated as tail elements, currently remain unchanged */ - /* TODO: configuration support for agnostic behavior */ - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_single_element(SEW, 0, vd, sum); + /* other elements in vd are treated as tail elements, currently remain unchanged */ + /* TODO: configuration support for agnostic behavior */ + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vredmaxu.vs.yaml b/arch/inst/V/vredmaxu.vs.yaml index d9e4400f3..548ab1858 100644 --- a/arch/inst/V/vredmaxu.vs.yaml +++ b/arch/inst/V/vredmaxu.vs.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vredmaxu.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000110-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vredmaxu.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000110-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ - - if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; - - if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ - - let 'n = num_elem_vs; - let 'd = num_elem_vd; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); - let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); - let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); - - sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ - foreach (i from 0 to (num_elem_vs - 1)) { - if mask[i] then { - sum = match funct6 { - MVV_VREDSUM => sum + vs2_val[i], - MVV_VREDAND => sum & vs2_val[i], - MVV_VREDOR => sum | vs2_val[i], - MVV_VREDXOR => sum ^ vs2_val[i], - MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), - MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), - MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), - MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); + let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ + + if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; + + if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ + + let 'n = num_elem_vs; + let 'd = num_elem_vd; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); + let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); + let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); + + sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ + foreach (i from 0 to (num_elem_vs - 1)) { + if mask[i] then { + sum = match funct6 { + MVV_VREDSUM => sum + vs2_val[i], + MVV_VREDAND => sum & vs2_val[i], + MVV_VREDOR => sum | vs2_val[i], + MVV_VREDXOR => sum ^ vs2_val[i], + MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), + MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), + MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), + MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) } - }; - - write_single_element(SEW, 0, vd, sum); - /* other elements in vd are treated as tail elements, currently remain unchanged */ - /* TODO: configuration support for agnostic behavior */ - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_single_element(SEW, 0, vd, sum); + /* other elements in vd are treated as tail elements, currently remain unchanged */ + /* TODO: configuration support for agnostic behavior */ + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vredmin.vs.yaml b/arch/inst/V/vredmin.vs.yaml index 7be16c435..41ac773bc 100644 --- a/arch/inst/V/vredmin.vs.yaml +++ b/arch/inst/V/vredmin.vs.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vredmin.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000101-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vredmin.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000101-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ - - if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; - - if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ - - let 'n = num_elem_vs; - let 'd = num_elem_vd; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); - let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); - let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); - - sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ - foreach (i from 0 to (num_elem_vs - 1)) { - if mask[i] then { - sum = match funct6 { - MVV_VREDSUM => sum + vs2_val[i], - MVV_VREDAND => sum & vs2_val[i], - MVV_VREDOR => sum | vs2_val[i], - MVV_VREDXOR => sum ^ vs2_val[i], - MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), - MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), - MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), - MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); + let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ + + if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; + + if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ + + let 'n = num_elem_vs; + let 'd = num_elem_vd; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); + let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); + let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); + + sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ + foreach (i from 0 to (num_elem_vs - 1)) { + if mask[i] then { + sum = match funct6 { + MVV_VREDSUM => sum + vs2_val[i], + MVV_VREDAND => sum & vs2_val[i], + MVV_VREDOR => sum | vs2_val[i], + MVV_VREDXOR => sum ^ vs2_val[i], + MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), + MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), + MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), + MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) } - }; - - write_single_element(SEW, 0, vd, sum); - /* other elements in vd are treated as tail elements, currently remain unchanged */ - /* TODO: configuration support for agnostic behavior */ - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_single_element(SEW, 0, vd, sum); + /* other elements in vd are treated as tail elements, currently remain unchanged */ + /* TODO: configuration support for agnostic behavior */ + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vredminu.vs.yaml b/arch/inst/V/vredminu.vs.yaml index 23b2eff3d..64c924b88 100644 --- a/arch/inst/V/vredminu.vs.yaml +++ b/arch/inst/V/vredminu.vs.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vredminu.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000100-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vredminu.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000100-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ - - if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; - - if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ - - let 'n = num_elem_vs; - let 'd = num_elem_vd; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); - let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); - let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); - - sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ - foreach (i from 0 to (num_elem_vs - 1)) { - if mask[i] then { - sum = match funct6 { - MVV_VREDSUM => sum + vs2_val[i], - MVV_VREDAND => sum & vs2_val[i], - MVV_VREDOR => sum | vs2_val[i], - MVV_VREDXOR => sum ^ vs2_val[i], - MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), - MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), - MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), - MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); + let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ + + if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; + + if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ + + let 'n = num_elem_vs; + let 'd = num_elem_vd; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); + let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); + let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); + + sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ + foreach (i from 0 to (num_elem_vs - 1)) { + if mask[i] then { + sum = match funct6 { + MVV_VREDSUM => sum + vs2_val[i], + MVV_VREDAND => sum & vs2_val[i], + MVV_VREDOR => sum | vs2_val[i], + MVV_VREDXOR => sum ^ vs2_val[i], + MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), + MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), + MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), + MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) } - }; - - write_single_element(SEW, 0, vd, sum); - /* other elements in vd are treated as tail elements, currently remain unchanged */ - /* TODO: configuration support for agnostic behavior */ - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_single_element(SEW, 0, vd, sum); + /* other elements in vd are treated as tail elements, currently remain unchanged */ + /* TODO: configuration support for agnostic behavior */ + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vredor.vs.yaml b/arch/inst/V/vredor.vs.yaml index a5832b5f6..3c54847de 100644 --- a/arch/inst/V/vredor.vs.yaml +++ b/arch/inst/V/vredor.vs.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vredor.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000010-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vredor.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000010-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ - - if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; - - if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ - - let 'n = num_elem_vs; - let 'd = num_elem_vd; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); - let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); - let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); - - sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ - foreach (i from 0 to (num_elem_vs - 1)) { - if mask[i] then { - sum = match funct6 { - MVV_VREDSUM => sum + vs2_val[i], - MVV_VREDAND => sum & vs2_val[i], - MVV_VREDOR => sum | vs2_val[i], - MVV_VREDXOR => sum ^ vs2_val[i], - MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), - MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), - MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), - MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); + let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ + + if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; + + if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ + + let 'n = num_elem_vs; + let 'd = num_elem_vd; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); + let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); + let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); + + sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ + foreach (i from 0 to (num_elem_vs - 1)) { + if mask[i] then { + sum = match funct6 { + MVV_VREDSUM => sum + vs2_val[i], + MVV_VREDAND => sum & vs2_val[i], + MVV_VREDOR => sum | vs2_val[i], + MVV_VREDXOR => sum ^ vs2_val[i], + MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), + MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), + MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), + MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) } - }; - - write_single_element(SEW, 0, vd, sum); - /* other elements in vd are treated as tail elements, currently remain unchanged */ - /* TODO: configuration support for agnostic behavior */ - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_single_element(SEW, 0, vd, sum); + /* other elements in vd are treated as tail elements, currently remain unchanged */ + /* TODO: configuration support for agnostic behavior */ + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vredsum.vs.yaml b/arch/inst/V/vredsum.vs.yaml index 03828a588..d254f4167 100644 --- a/arch/inst/V/vredsum.vs.yaml +++ b/arch/inst/V/vredsum.vs.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vredsum.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000000-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vredsum.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000000-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ - - if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; - - if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ - - let 'n = num_elem_vs; - let 'd = num_elem_vd; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); - let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); - let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); - - sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ - foreach (i from 0 to (num_elem_vs - 1)) { - if mask[i] then { - sum = match funct6 { - MVV_VREDSUM => sum + vs2_val[i], - MVV_VREDAND => sum & vs2_val[i], - MVV_VREDOR => sum | vs2_val[i], - MVV_VREDXOR => sum ^ vs2_val[i], - MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), - MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), - MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), - MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); + let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ + + if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; + + if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ + + let 'n = num_elem_vs; + let 'd = num_elem_vd; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); + let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); + let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); + + sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ + foreach (i from 0 to (num_elem_vs - 1)) { + if mask[i] then { + sum = match funct6 { + MVV_VREDSUM => sum + vs2_val[i], + MVV_VREDAND => sum & vs2_val[i], + MVV_VREDOR => sum | vs2_val[i], + MVV_VREDXOR => sum ^ vs2_val[i], + MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), + MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), + MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), + MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) } - }; - - write_single_element(SEW, 0, vd, sum); - /* other elements in vd are treated as tail elements, currently remain unchanged */ - /* TODO: configuration support for agnostic behavior */ - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_single_element(SEW, 0, vd, sum); + /* other elements in vd are treated as tail elements, currently remain unchanged */ + /* TODO: configuration support for agnostic behavior */ + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vredxor.vs.yaml b/arch/inst/V/vredxor.vs.yaml index 84ac9e70a..bf47cb601 100644 --- a/arch/inst/V/vredxor.vs.yaml +++ b/arch/inst/V/vredxor.vs.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vredxor.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000011-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vredxor.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000011-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ - - if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; - - if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ - - let 'n = num_elem_vs; - let 'd = num_elem_vd; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); - let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); - let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); - - sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ - foreach (i from 0 to (num_elem_vs - 1)) { - if mask[i] then { - sum = match funct6 { - MVV_VREDSUM => sum + vs2_val[i], - MVV_VREDAND => sum & vs2_val[i], - MVV_VREDOR => sum | vs2_val[i], - MVV_VREDXOR => sum ^ vs2_val[i], - MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), - MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), - MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), - MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem_vs = get_num_elem(LMUL_pow, SEW); + let num_elem_vd = get_num_elem(0, SEW); /* vd regardless of LMUL setting */ + + if illegal_reduction() then { handle_illegal(); return RETIRE_FAIL }; + + if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ + + let 'n = num_elem_vs; + let 'd = num_elem_vd; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); + let vd_val : vector('d, dec, bits('m)) = read_vreg(num_elem_vd, SEW, 0, vd); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); + let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); + + sum : bits('m) = read_single_element(SEW, 0, vs1); /* vs1 regardless of LMUL setting */ + foreach (i from 0 to (num_elem_vs - 1)) { + if mask[i] then { + sum = match funct6 { + MVV_VREDSUM => sum + vs2_val[i], + MVV_VREDAND => sum & vs2_val[i], + MVV_VREDOR => sum | vs2_val[i], + MVV_VREDXOR => sum ^ vs2_val[i], + MVV_VREDMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(sum))), + MVV_VREDMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(sum))), + MVV_VREDMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(sum))), + MVV_VREDMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(sum))) } - }; - - write_single_element(SEW, 0, vd, sum); - /* other elements in vd are treated as tail elements, currently remain unchanged */ - /* TODO: configuration support for agnostic behavior */ - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_single_element(SEW, 0, vd, sum); + /* other elements in vd are treated as tail elements, currently remain unchanged */ + /* TODO: configuration support for agnostic behavior */ + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vrem.vv.yaml b/arch/inst/V/vrem.vv.yaml index 060702273..175ce9362 100644 --- a/arch/inst/V/vrem.vv.yaml +++ b/arch/inst/V/vrem.vv.yaml @@ -1,109 +1,110 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vrem.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100011-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vrem.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100011-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), - MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), - MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VDIVU => { - let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - to_bits(SEW, q) - }, - MVV_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVV_VREMU => { - let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVV_VREM => { - let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), + MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), + MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VDIVU => { + let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + to_bits(SEW, q) + }, + MVV_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVV_VREMU => { + let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVV_VREM => { + let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vrem.vx.yaml b/arch/inst/V/vrem.vx.yaml index d445e27aa..d04de82d6 100644 --- a/arch/inst/V/vrem.vx.yaml +++ b/arch/inst/V/vrem.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vrem.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100011-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vrem.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100011-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vremu.vv.yaml b/arch/inst/V/vremu.vv.yaml index c2cb577f4..e0f547263 100644 --- a/arch/inst/V/vremu.vv.yaml +++ b/arch/inst/V/vremu.vv.yaml @@ -1,109 +1,110 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vremu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100010-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vremu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100010-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVV_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), - MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), - MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), - MVV_VDIVU => { - let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - to_bits(SEW, q) - }, - MVV_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVV_VREMU => { - let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVV_VREM => { - let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVV_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i]); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVV_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), 0), + MVV_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(vs1_val[i]), SEW), + MVV_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(vs1_val[i]), SEW), + MVV_VDIVU => { + let q : int = if unsigned(vs1_val[i]) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + to_bits(SEW, q) + }, + MVV_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(vs1_val[i]) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVV_VREMU => { + let r : int = if unsigned(vs1_val[i]) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVV_VREM => { + let r : int = if signed(vs1_val[i]) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(vs1_val[i])); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vremu.vx.yaml b/arch/inst/V/vremu.vx.yaml index 8e3e772a6..f18797128 100644 --- a/arch/inst/V/vremu.vx.yaml +++ b/arch/inst/V/vremu.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vremu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100010-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vremu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100010-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vrgather.vi.yaml b/arch/inst/V/vrgather.vi.yaml index 098219871..cce4802a6 100644 --- a/arch/inst/V/vrgather.vi.yaml +++ b/arch/inst/V/vrgather.vi.yaml @@ -1,80 +1,81 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vrgather.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 001100-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vrgather.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 001100-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : nat = unsigned(zero_extend(sizeof(xlen), simm)); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VSLIDEUP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i >= imm_val then vs2_val[i - imm_val] else vd_val[i] - }, - VI_VSLIDEDOWN => { - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX > 0 & VLMAX <= 'n); - if i + imm_val < VLMAX then vs2_val[i + imm_val] else zeros() - }, - VI_VRGATHER => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX > 0 & VLMAX <= 'n); - if imm_val < VLMAX then vs2_val[imm_val] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : nat = unsigned(zero_extend(sizeof(xlen), simm)); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VSLIDEUP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i >= imm_val then vs2_val[i - imm_val] else vd_val[i] + }, + VI_VSLIDEDOWN => { + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX > 0 & VLMAX <= 'n); + if i + imm_val < VLMAX then vs2_val[i + imm_val] else zeros() + }, + VI_VRGATHER => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX > 0 & VLMAX <= 'n); + if imm_val < VLMAX then vs2_val[imm_val] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vrgather.vv.yaml b/arch/inst/V/vrgather.vv.yaml index f7a2f802a..3b902476c 100644 --- a/arch/inst/V/vrgather.vv.yaml +++ b/arch/inst/V/vrgather.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vrgather.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 001100-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vrgather.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 001100-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vrgather.vx.yaml b/arch/inst/V/vrgather.vx.yaml index f84f5128a..fef288091 100644 --- a/arch/inst/V/vrgather.vx.yaml +++ b/arch/inst/V/vrgather.vx.yaml @@ -1,80 +1,81 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vrgather.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001100-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vrgather.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001100-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : nat = unsigned(X(rs1)); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VSLIDEUP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i >= rs1_val then vs2_val[i - rs1_val] else vd_val[i] - }, - VX_VSLIDEDOWN => { - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX > 0 & VLMAX <= 'n); - if i + rs1_val < VLMAX then vs2_val[i + rs1_val] else zeros() - }, - VX_VRGATHER => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX > 0 & VLMAX <= 'n); - if rs1_val < VLMAX then vs2_val[rs1_val] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : nat = unsigned(X(rs1)); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VSLIDEUP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i >= rs1_val then vs2_val[i - rs1_val] else vd_val[i] + }, + VX_VSLIDEDOWN => { + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX > 0 & VLMAX <= 'n); + if i + rs1_val < VLMAX then vs2_val[i + rs1_val] else zeros() + }, + VX_VRGATHER => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX > 0 & VLMAX <= 'n); + if rs1_val < VLMAX then vs2_val[rs1_val] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vrgatherei16.vv.yaml b/arch/inst/V/vrgatherei16.vv.yaml index bdfa18298..6588d9cc9 100644 --- a/arch/inst/V/vrgatherei16.vv.yaml +++ b/arch/inst/V/vrgatherei16.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vrgatherei16.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 001110-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vrgatherei16.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 001110-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vrsub.vi.yaml b/arch/inst/V/vrsub.vi.yaml index 80da62cdd..c2e1a4fe1 100644 --- a/arch/inst/V/vrsub.vi.yaml +++ b/arch/inst/V/vrsub.vi.yaml @@ -1,94 +1,95 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vrsub.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 000011-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vrsub.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 000011-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VADD => vs2_val[i] + imm_val, - VI_VRSUB => imm_val - vs2_val[i], - VI_VAND => vs2_val[i] & imm_val, - VI_VOR => vs2_val[i] | imm_val, - VI_VXOR => vs2_val[i] ^ imm_val, - VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), - VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), - VI_VSLL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] << shift_amount - }, - VI_VSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] >> shift_amount - }, - VI_VSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VI_VSSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VI_VSSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VADD => vs2_val[i] + imm_val, + VI_VRSUB => imm_val - vs2_val[i], + VI_VAND => vs2_val[i] & imm_val, + VI_VOR => vs2_val[i] | imm_val, + VI_VXOR => vs2_val[i] ^ imm_val, + VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), + VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), + VI_VSLL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] << shift_amount + }, + VI_VSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] >> shift_amount + }, + VI_VSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VI_VSSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VI_VSSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vrsub.vx.yaml b/arch/inst/V/vrsub.vx.yaml index 1aa11f6a4..28dc3fd33 100644 --- a/arch/inst/V/vrsub.vx.yaml +++ b/arch/inst/V/vrsub.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vrsub.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000011-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vrsub.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000011-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vs1r.v.yaml b/arch/inst/V/vs1r.v.yaml index 2a7df757d..89a88c823 100644 --- a/arch/inst/V/vs1r.v.yaml +++ b/arch/inst/V/vs1r.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vs1r.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vs3 - encoding: - match: 000000101000-----000-----0100111 - variables: - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vs1r.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vs3 +encoding: + match: 000000101000-----000-----0100111 + variables: + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vs2r.v.yaml b/arch/inst/V/vs2r.v.yaml index 5b948f5aa..1f8e6a218 100644 --- a/arch/inst/V/vs2r.v.yaml +++ b/arch/inst/V/vs2r.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vs2r.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vs3 - encoding: - match: 001000101000-----000-----0100111 - variables: - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vs2r.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vs3 +encoding: + match: 001000101000-----000-----0100111 + variables: + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vs4r.v.yaml b/arch/inst/V/vs4r.v.yaml index 08c794196..5c2cf8bc2 100644 --- a/arch/inst/V/vs4r.v.yaml +++ b/arch/inst/V/vs4r.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vs4r.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vs3 - encoding: - match: 011000101000-----000-----0100111 - variables: - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vs4r.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vs3 +encoding: + match: 011000101000-----000-----0100111 + variables: + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vs8r.v.yaml b/arch/inst/V/vs8r.v.yaml index 4e3570bca..2eb6a086e 100644 --- a/arch/inst/V/vs8r.v.yaml +++ b/arch/inst/V/vs8r.v.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vs8r.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vs3 - encoding: - match: 111000101000-----000-----0100111 - variables: - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vs8r.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vs3 +encoding: + match: 111000101000-----000-----0100111 + variables: + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vsadd.vi.yaml b/arch/inst/V/vsadd.vi.yaml index cc27ee2d0..0d8078033 100644 --- a/arch/inst/V/vsadd.vi.yaml +++ b/arch/inst/V/vsadd.vi.yaml @@ -1,94 +1,95 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsadd.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 100001-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsadd.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 100001-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VADD => vs2_val[i] + imm_val, - VI_VRSUB => imm_val - vs2_val[i], - VI_VAND => vs2_val[i] & imm_val, - VI_VOR => vs2_val[i] | imm_val, - VI_VXOR => vs2_val[i] ^ imm_val, - VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), - VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), - VI_VSLL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] << shift_amount - }, - VI_VSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] >> shift_amount - }, - VI_VSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VI_VSSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VI_VSSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VADD => vs2_val[i] + imm_val, + VI_VRSUB => imm_val - vs2_val[i], + VI_VAND => vs2_val[i] & imm_val, + VI_VOR => vs2_val[i] | imm_val, + VI_VXOR => vs2_val[i] ^ imm_val, + VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), + VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), + VI_VSLL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] << shift_amount + }, + VI_VSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] >> shift_amount + }, + VI_VSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VI_VSSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VI_VSSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsadd.vv.yaml b/arch/inst/V/vsadd.vv.yaml index c3dd3509e..d293482c7 100644 --- a/arch/inst/V/vsadd.vv.yaml +++ b/arch/inst/V/vsadd.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsadd.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100001-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsadd.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100001-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsadd.vx.yaml b/arch/inst/V/vsadd.vx.yaml index db5dc0585..cb9ae0d4d 100644 --- a/arch/inst/V/vsadd.vx.yaml +++ b/arch/inst/V/vsadd.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsadd.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100001-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsadd.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100001-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsaddu.vi.yaml b/arch/inst/V/vsaddu.vi.yaml index 1ba58a7ba..5c264d554 100644 --- a/arch/inst/V/vsaddu.vi.yaml +++ b/arch/inst/V/vsaddu.vi.yaml @@ -1,94 +1,95 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsaddu.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 100000-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsaddu.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 100000-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VADD => vs2_val[i] + imm_val, - VI_VRSUB => imm_val - vs2_val[i], - VI_VAND => vs2_val[i] & imm_val, - VI_VOR => vs2_val[i] | imm_val, - VI_VXOR => vs2_val[i] ^ imm_val, - VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), - VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), - VI_VSLL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] << shift_amount - }, - VI_VSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] >> shift_amount - }, - VI_VSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VI_VSSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VI_VSSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VADD => vs2_val[i] + imm_val, + VI_VRSUB => imm_val - vs2_val[i], + VI_VAND => vs2_val[i] & imm_val, + VI_VOR => vs2_val[i] | imm_val, + VI_VXOR => vs2_val[i] ^ imm_val, + VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), + VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), + VI_VSLL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] << shift_amount + }, + VI_VSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] >> shift_amount + }, + VI_VSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VI_VSSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VI_VSSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsaddu.vv.yaml b/arch/inst/V/vsaddu.vv.yaml index 213958446..870e4ab1c 100644 --- a/arch/inst/V/vsaddu.vv.yaml +++ b/arch/inst/V/vsaddu.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsaddu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100000-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsaddu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100000-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsaddu.vx.yaml b/arch/inst/V/vsaddu.vx.yaml index 6ff0377e2..eb1916e2b 100644 --- a/arch/inst/V/vsaddu.vx.yaml +++ b/arch/inst/V/vsaddu.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsaddu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100000-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsaddu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100000-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsbc.vvm.yaml b/arch/inst/V/vsbc.vvm.yaml index 3c4ac1b5f..0ae6c376b 100644 --- a/arch/inst/V/vsbc.vvm.yaml +++ b/arch/inst/V/vsbc.vvm.yaml @@ -1,69 +1,70 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsbc.vvm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, vs1, vd - encoding: - match: 0100100----------000-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsbc.vvm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, vs1, vd +encoding: + match: 0100100----------000-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - /* for bypassing normal masking in init_masked_result */ - vec_trues : vector('n, dec, bool) = undefined; - foreach (i from 0 to (num_elem - 1)) { - vec_trues[i] = true - }; - - let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vec_trues); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VVMS_VADC => to_bits(SEW, unsigned(vs2_val[i]) + unsigned(vs1_val[i]) + unsigned(bool_to_bits(vm_val[i]))), - VVMS_VSBC => to_bits(SEW, unsigned(vs2_val[i]) - unsigned(vs1_val[i]) - unsigned(bool_to_bits(vm_val[i]))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + /* for bypassing normal masking in init_masked_result */ + vec_trues : vector('n, dec, bool) = undefined; + foreach (i from 0 to (num_elem - 1)) { + vec_trues[i] = true + }; + + let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vec_trues); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VVMS_VADC => to_bits(SEW, unsigned(vs2_val[i]) + unsigned(vs1_val[i]) + unsigned(bool_to_bits(vm_val[i]))), + VVMS_VSBC => to_bits(SEW, unsigned(vs2_val[i]) - unsigned(vs1_val[i]) - unsigned(bool_to_bits(vm_val[i]))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsbc.vxm.yaml b/arch/inst/V/vsbc.vxm.yaml index 4e9c0a4a8..5731aed41 100644 --- a/arch/inst/V/vsbc.vxm.yaml +++ b/arch/inst/V/vsbc.vxm.yaml @@ -1,69 +1,70 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsbc.vxm: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vs2, xs1, vd - encoding: - match: 0100100----------100-----1010111 - variables: - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsbc.vxm +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vs2, xs1, vd +encoding: + match: 0100100----------100-----1010111 + variables: + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - /* for bypassing normal masking in init_masked_result */ - vec_trues : vector('n, dec, bool) = undefined; - foreach (i from 0 to (num_elem - 1)) { - vec_trues[i] = true - }; - - let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vec_trues); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VXMS_VADC => to_bits(SEW, unsigned(vs2_val[i]) + unsigned(rs1_val) + unsigned(bool_to_bits(vm_val[i]))), - VXMS_VSBC => to_bits(SEW, unsigned(vs2_val[i]) - unsigned(rs1_val) - unsigned(bool_to_bits(vm_val[i]))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_vd_masked(vd) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + /* for bypassing normal masking in init_masked_result */ + vec_trues : vector('n, dec, bool) = undefined; + foreach (i from 0 to (num_elem - 1)) { + vec_trues[i] = true + }; + + let vm_val : vector('n, dec, bool) = read_vmask_carry(num_elem, 0b0, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vec_trues); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VXMS_VADC => to_bits(SEW, unsigned(vs2_val[i]) + unsigned(rs1_val) + unsigned(bool_to_bits(vm_val[i]))), + VXMS_VSBC => to_bits(SEW, unsigned(vs2_val[i]) - unsigned(rs1_val) - unsigned(bool_to_bits(vm_val[i]))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vse16.v.yaml b/arch/inst/V/vse16.v.yaml index 3e916696d..dfd3b2b0a 100644 --- a/arch/inst/V/vse16.v.yaml +++ b/arch/inst/V/vse16.v.yaml @@ -1,45 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vse16.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs1, vs3 - encoding: - match: 000000-00000-----101-----0100111 - variables: - - name: vm - location: 25-25 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vse16.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs1, vs3 +encoding: + match: 000000-00000-----101-----0100111 + variables: + - name: vm + location: 25-25 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vsseg(nf_int, vm, vs3, load_width_bytes, rs1, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vsseg(nf_int, vm, vs3, load_width_bytes, rs1, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vse32.v.yaml b/arch/inst/V/vse32.v.yaml index 36d79bf40..9e067d782 100644 --- a/arch/inst/V/vse32.v.yaml +++ b/arch/inst/V/vse32.v.yaml @@ -1,45 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vse32.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs1, vs3 - encoding: - match: 000000-00000-----110-----0100111 - variables: - - name: vm - location: 25-25 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vse32.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs1, vs3 +encoding: + match: 000000-00000-----110-----0100111 + variables: + - name: vm + location: 25-25 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vsseg(nf_int, vm, vs3, load_width_bytes, rs1, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vsseg(nf_int, vm, vs3, load_width_bytes, rs1, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vse64.v.yaml b/arch/inst/V/vse64.v.yaml index f1cac345e..1744b91e1 100644 --- a/arch/inst/V/vse64.v.yaml +++ b/arch/inst/V/vse64.v.yaml @@ -1,45 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vse64.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs1, vs3 - encoding: - match: 000000-00000-----111-----0100111 - variables: - - name: vm - location: 25-25 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vse64.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs1, vs3 +encoding: + match: 000000-00000-----111-----0100111 + variables: + - name: vm + location: 25-25 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vsseg(nf_int, vm, vs3, load_width_bytes, rs1, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vsseg(nf_int, vm, vs3, load_width_bytes, rs1, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vse8.v.yaml b/arch/inst/V/vse8.v.yaml index e33f9dae0..fd9223819 100644 --- a/arch/inst/V/vse8.v.yaml +++ b/arch/inst/V/vse8.v.yaml @@ -1,45 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vse8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs1, vs3 - encoding: - match: 000000-00000-----000-----0100111 - variables: - - name: vm - location: 25-25 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vse8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs1, vs3 +encoding: + match: 000000-00000-----000-----0100111 + variables: + - name: vm + location: 25-25 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vsseg(nf_int, vm, vs3, load_width_bytes, rs1, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vsseg(nf_int, vm, vs3, load_width_bytes, rs1, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vsetivli.yaml b/arch/inst/V/vsetivli.yaml index 1e62eded5..f8b35e0b7 100644 --- a/arch/inst/V/vsetivli.yaml +++ b/arch/inst/V/vsetivli.yaml @@ -1,74 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsetivli: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xd, imm - encoding: - match: 11---------------111-----1010111 - variables: - - name: zimm10 - location: 29-20 - - name: uimm - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsetivli +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xd, imm +encoding: + match: 11---------------111-----1010111 + variables: + - name: zimm10 + location: 29-20 + - name: uimm + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - 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 */ - vtype->bits() = 0b0 @ zeros(sizeof(xlen) - 9) @ ma @ ta @ sew @ lmul; - - /* 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); - let AVL = unsigned(uimm); /* AVL is encoded as 5-bit zero-extended imm in the rs1 field */ - - /* set vl according to VLMAX and AVL */ - 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 +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 */ + vtype->bits() = 0b0 @ zeros(sizeof(xlen) - 9) @ ma @ ta @ sew @ lmul; + + /* 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 */ - X(rd) = vl; + 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 - } + return RETIRE_SUCCESS + }; + let VLMAX = int_power(2, VLEN_pow + LMUL_pow_new - SEW_pow_new); + let AVL = unsigned(uimm); /* AVL is encoded as 5-bit zero-extended imm in the rs1 field */ + + /* set vl according to VLMAX and AVL */ + 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; + print_reg("CSR vtype <- " ^ BitStr(vtype.bits())); + print_reg("CSR vl <- " ^ BitStr(vl)); - \ No newline at end of file + /* reset vstart to 0 */ + vstart = zeros(); + print_reg("CSR vstart <- " ^ BitStr(vstart)); + + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsetvl.yaml b/arch/inst/V/vsetvl.yaml index 0ec052674..c7341e9da 100644 --- a/arch/inst/V/vsetvl.yaml +++ b/arch/inst/V/vsetvl.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsetvl: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs2, xs1, xd - encoding: - match: 1000000----------111-----1010111 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsetvl +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs2, xs1, xd +encoding: + match: 1000000----------111-----1010111 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/V/vsetvli.yaml b/arch/inst/V/vsetvli.yaml index 3cc033558..ad90125f4 100644 --- a/arch/inst/V/vsetvli.yaml +++ b/arch/inst/V/vsetvli.yaml @@ -1,101 +1,103 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsetvli: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, xd, imm - encoding: - match: 0----------------111-----1010111 - variables: - - name: zimm11 - location: 30-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsetvli +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, xd, imm +encoding: + match: 0----------------111-----1010111 + variables: + - name: zimm11 + location: 30-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - 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 { +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)); - 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 - } + } + }; + 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 + } + + diff --git a/arch/inst/V/vsext.vf2.yaml b/arch/inst/V/vsext.vf2.yaml index 8fb3f171d..e62d41030 100644 --- a/arch/inst/V/vsext.vf2.yaml +++ b/arch/inst/V/vsext.vf2.yaml @@ -1,68 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsext.vf2: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------00111010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsext.vf2 +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------00111010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_half = SEW / 2; - let LMUL_pow_half = LMUL_pow - 1; - - if illegal_variable_width(vd, vm, SEW_half, LMUL_pow_half) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_half, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_half; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_half, LMUL_pow_half, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW > SEW_half); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VEXT2_ZVF2 => zero_extend(vs2_val[i]), - VEXT2_SVF2 => sign_extend(vs2_val[i]) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_half = SEW / 2; + let LMUL_pow_half = LMUL_pow - 1; + + if illegal_variable_width(vd, vm, SEW_half, LMUL_pow_half) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_half, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_half; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_half, LMUL_pow_half, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW > SEW_half); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VEXT2_ZVF2 => zero_extend(vs2_val[i]), + VEXT2_SVF2 => sign_extend(vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsext.vf4.yaml b/arch/inst/V/vsext.vf4.yaml index 16400dd5e..93c595aae 100644 --- a/arch/inst/V/vsext.vf4.yaml +++ b/arch/inst/V/vsext.vf4.yaml @@ -1,68 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsext.vf4: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------00101010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsext.vf4 +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------00101010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_quart = SEW / 4; - let LMUL_pow_quart = LMUL_pow - 2; - - if illegal_variable_width(vd, vm, SEW_quart, LMUL_pow_quart) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_quart, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_quart; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_quart, LMUL_pow_quart, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW > SEW_quart); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VEXT4_ZVF4 => zero_extend(vs2_val[i]), - VEXT4_SVF4 => sign_extend(vs2_val[i]) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_quart = SEW / 4; + let LMUL_pow_quart = LMUL_pow - 2; + + if illegal_variable_width(vd, vm, SEW_quart, LMUL_pow_quart) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_quart, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_quart; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_quart, LMUL_pow_quart, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW > SEW_quart); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VEXT4_ZVF4 => zero_extend(vs2_val[i]), + VEXT4_SVF4 => sign_extend(vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsext.vf8.yaml b/arch/inst/V/vsext.vf8.yaml index 38cbc1b71..14cb8c222 100644 --- a/arch/inst/V/vsext.vf8.yaml +++ b/arch/inst/V/vsext.vf8.yaml @@ -1,68 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsext.vf8: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------00011010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsext.vf8 +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------00011010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_eighth = SEW / 8; - let LMUL_pow_eighth = LMUL_pow - 3; - - if illegal_variable_width(vd, vm, SEW_eighth, LMUL_pow_eighth) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_eighth, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_eighth; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_eighth, LMUL_pow_eighth, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW > SEW_eighth); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VEXT8_ZVF8 => zero_extend(vs2_val[i]), - VEXT8_SVF8 => sign_extend(vs2_val[i]) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_eighth = SEW / 8; + let LMUL_pow_eighth = LMUL_pow - 3; + + if illegal_variable_width(vd, vm, SEW_eighth, LMUL_pow_eighth) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_eighth, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_eighth; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_eighth, LMUL_pow_eighth, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW > SEW_eighth); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VEXT8_ZVF8 => zero_extend(vs2_val[i]), + VEXT8_SVF8 => sign_extend(vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vslide1down.vx.yaml b/arch/inst/V/vslide1down.vx.yaml index c712fed9b..604c111f9 100644 --- a/arch/inst/V/vslide1down.vx.yaml +++ b/arch/inst/V/vslide1down.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vslide1down.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001111-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vslide1down.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001111-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vslide1up.vx.yaml b/arch/inst/V/vslide1up.vx.yaml index bb5566fd4..7879c052c 100644 --- a/arch/inst/V/vslide1up.vx.yaml +++ b/arch/inst/V/vslide1up.vx.yaml @@ -1,118 +1,119 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vslide1up.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001110-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vslide1up.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001110-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - MVX_VAADDU => { - let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VAADD => { - let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_add, 1); - slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUBU => { - let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VASUB => { - let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); - let rounding_incr = get_fixed_rounding_incr(result_sub, 1); - slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) - }, - MVX_VSLIDE1UP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i == 0 then rs1_val else vs2_val[i - 1] - }, - MVX_VSLIDE1DOWN => { - let last_elem = get_end_element(); - assert(last_elem < num_elem); - if i < last_elem then vs2_val[i + 1] else rs1_val - }, - MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), - MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), - MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), - MVX_VDIVU => { - let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); - to_bits(SEW, q) - }, - MVX_VDIV => { - let elem_max : int = 2 ^ (SEW - 1) - 1; - let elem_min : int = 0 - 2 ^ (SEW - 1); - let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* check for signed overflow */ - let q' : int = if q > elem_max then elem_min else q; - to_bits(SEW, q') - }, - MVX_VREMU => { - let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - }, - MVX_VREM => { - let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); - /* signed overflow case returns zero naturally as required due to -1 divisor */ - to_bits(SEW, r) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + MVX_VAADDU => { + let result_add = zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VAADD => { + let result_add = sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_add, 1); + slice(result_add >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUBU => { + let result_sub = zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VASUB => { + let result_sub = sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val); + let rounding_incr = get_fixed_rounding_incr(result_sub, 1); + slice(result_sub >> 1, 0, 'm) + zero_extend('m, rounding_incr) + }, + MVX_VSLIDE1UP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i == 0 then rs1_val else vs2_val[i - 1] + }, + MVX_VSLIDE1DOWN => { + let last_elem = get_end_element(); + assert(last_elem < num_elem); + if i < last_elem then vs2_val[i + 1] else rs1_val + }, + MVX_VMUL => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), 0), + MVX_VMULH => get_slice_int(SEW, signed(vs2_val[i]) * signed(rs1_val), SEW), + MVX_VMULHU => get_slice_int(SEW, unsigned(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VMULHSU => get_slice_int(SEW, signed(vs2_val[i]) * unsigned(rs1_val), SEW), + MVX_VDIVU => { + let q : int = if unsigned(rs1_val) == 0 then -1 else quot_round_zero(unsigned(vs2_val[i]), unsigned(rs1_val)); + to_bits(SEW, q) + }, + MVX_VDIV => { + let elem_max : int = 2 ^ (SEW - 1) - 1; + let elem_min : int = 0 - 2 ^ (SEW - 1); + let q : int = if signed(rs1_val) == 0 then -1 else quot_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* check for signed overflow */ + let q' : int = if q > elem_max then elem_min else q; + to_bits(SEW, q') + }, + MVX_VREMU => { + let r : int = if unsigned(rs1_val) == 0 then unsigned(vs2_val[i]) else rem_round_zero(unsigned(vs2_val[i]), unsigned (rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + }, + MVX_VREM => { + let r : int = if signed(rs1_val) == 0 then signed(vs2_val[i]) else rem_round_zero(signed(vs2_val[i]), signed(rs1_val)); + /* signed overflow case returns zero naturally as required due to -1 divisor */ + to_bits(SEW, r) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vslidedown.vi.yaml b/arch/inst/V/vslidedown.vi.yaml index 0cb1ca8a1..2d512fef9 100644 --- a/arch/inst/V/vslidedown.vi.yaml +++ b/arch/inst/V/vslidedown.vi.yaml @@ -1,80 +1,81 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vslidedown.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 001111-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vslidedown.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 001111-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : nat = unsigned(zero_extend(sizeof(xlen), simm)); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VSLIDEUP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i >= imm_val then vs2_val[i - imm_val] else vd_val[i] - }, - VI_VSLIDEDOWN => { - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX > 0 & VLMAX <= 'n); - if i + imm_val < VLMAX then vs2_val[i + imm_val] else zeros() - }, - VI_VRGATHER => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX > 0 & VLMAX <= 'n); - if imm_val < VLMAX then vs2_val[imm_val] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : nat = unsigned(zero_extend(sizeof(xlen), simm)); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VSLIDEUP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i >= imm_val then vs2_val[i - imm_val] else vd_val[i] + }, + VI_VSLIDEDOWN => { + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX > 0 & VLMAX <= 'n); + if i + imm_val < VLMAX then vs2_val[i + imm_val] else zeros() + }, + VI_VRGATHER => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX > 0 & VLMAX <= 'n); + if imm_val < VLMAX then vs2_val[imm_val] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vslidedown.vx.yaml b/arch/inst/V/vslidedown.vx.yaml index 615de29e2..265c9b957 100644 --- a/arch/inst/V/vslidedown.vx.yaml +++ b/arch/inst/V/vslidedown.vx.yaml @@ -1,80 +1,81 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vslidedown.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001111-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vslidedown.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001111-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : nat = unsigned(X(rs1)); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VSLIDEUP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i >= rs1_val then vs2_val[i - rs1_val] else vd_val[i] - }, - VX_VSLIDEDOWN => { - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX > 0 & VLMAX <= 'n); - if i + rs1_val < VLMAX then vs2_val[i + rs1_val] else zeros() - }, - VX_VRGATHER => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX > 0 & VLMAX <= 'n); - if rs1_val < VLMAX then vs2_val[rs1_val] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : nat = unsigned(X(rs1)); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VSLIDEUP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i >= rs1_val then vs2_val[i - rs1_val] else vd_val[i] + }, + VX_VSLIDEDOWN => { + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX > 0 & VLMAX <= 'n); + if i + rs1_val < VLMAX then vs2_val[i + rs1_val] else zeros() + }, + VX_VRGATHER => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX > 0 & VLMAX <= 'n); + if rs1_val < VLMAX then vs2_val[rs1_val] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vslideup.vi.yaml b/arch/inst/V/vslideup.vi.yaml index 20ecb7f10..1f21c090c 100644 --- a/arch/inst/V/vslideup.vi.yaml +++ b/arch/inst/V/vslideup.vi.yaml @@ -1,80 +1,81 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vslideup.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 001110-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vslideup.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 001110-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : nat = unsigned(zero_extend(sizeof(xlen), simm)); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VSLIDEUP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i >= imm_val then vs2_val[i - imm_val] else vd_val[i] - }, - VI_VSLIDEDOWN => { - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX > 0 & VLMAX <= 'n); - if i + imm_val < VLMAX then vs2_val[i + imm_val] else zeros() - }, - VI_VRGATHER => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX > 0 & VLMAX <= 'n); - if imm_val < VLMAX then vs2_val[imm_val] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : nat = unsigned(zero_extend(sizeof(xlen), simm)); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VSLIDEUP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i >= imm_val then vs2_val[i - imm_val] else vd_val[i] + }, + VI_VSLIDEDOWN => { + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX > 0 & VLMAX <= 'n); + if i + imm_val < VLMAX then vs2_val[i + imm_val] else zeros() + }, + VI_VRGATHER => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX > 0 & VLMAX <= 'n); + if imm_val < VLMAX then vs2_val[imm_val] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vslideup.vx.yaml b/arch/inst/V/vslideup.vx.yaml index 4ae8d2240..3e7b93e0d 100644 --- a/arch/inst/V/vslideup.vx.yaml +++ b/arch/inst/V/vslideup.vx.yaml @@ -1,80 +1,81 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vslideup.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001110-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vslideup.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001110-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : nat = unsigned(X(rs1)); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VSLIDEUP => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - if i >= rs1_val then vs2_val[i - rs1_val] else vd_val[i] - }, - VX_VSLIDEDOWN => { - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX > 0 & VLMAX <= 'n); - if i + rs1_val < VLMAX then vs2_val[i + rs1_val] else zeros() - }, - VX_VRGATHER => { - if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX > 0 & VLMAX <= 'n); - if rs1_val < VLMAX then vs2_val[rs1_val] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : nat = unsigned(X(rs1)); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VSLIDEUP => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + if i >= rs1_val then vs2_val[i - rs1_val] else vd_val[i] + }, + VX_VSLIDEDOWN => { + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX > 0 & VLMAX <= 'n); + if i + rs1_val < VLMAX then vs2_val[i + rs1_val] else zeros() + }, + VX_VRGATHER => { + if (vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX > 0 & VLMAX <= 'n); + if rs1_val < VLMAX then vs2_val[rs1_val] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsll.vi.yaml b/arch/inst/V/vsll.vi.yaml index 1730c7dd1..3365ef202 100644 --- a/arch/inst/V/vsll.vi.yaml +++ b/arch/inst/V/vsll.vi.yaml @@ -1,94 +1,95 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsll.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 100101-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsll.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 100101-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VADD => vs2_val[i] + imm_val, - VI_VRSUB => imm_val - vs2_val[i], - VI_VAND => vs2_val[i] & imm_val, - VI_VOR => vs2_val[i] | imm_val, - VI_VXOR => vs2_val[i] ^ imm_val, - VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), - VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), - VI_VSLL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] << shift_amount - }, - VI_VSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] >> shift_amount - }, - VI_VSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VI_VSSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VI_VSSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VADD => vs2_val[i] + imm_val, + VI_VRSUB => imm_val - vs2_val[i], + VI_VAND => vs2_val[i] & imm_val, + VI_VOR => vs2_val[i] | imm_val, + VI_VXOR => vs2_val[i] ^ imm_val, + VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), + VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), + VI_VSLL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] << shift_amount + }, + VI_VSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] >> shift_amount + }, + VI_VSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VI_VSSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VI_VSSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsll.vv.yaml b/arch/inst/V/vsll.vv.yaml index b9bdfa4b6..d3298a000 100644 --- a/arch/inst/V/vsll.vv.yaml +++ b/arch/inst/V/vsll.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsll.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100101-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsll.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100101-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsll.vx.yaml b/arch/inst/V/vsll.vx.yaml index c1e144136..0cd9cceb5 100644 --- a/arch/inst/V/vsll.vx.yaml +++ b/arch/inst/V/vsll.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsll.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100101-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsll.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100101-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsm.v.yaml b/arch/inst/V/vsm.v.yaml index 5da29c8f1..4d9ae9140 100644 --- a/arch/inst/V/vsm.v.yaml +++ b/arch/inst/V/vsm.v.yaml @@ -1,41 +1,42 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsm.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: xs1, vs3 - encoding: - match: 000000101011-----000-----0100111 - variables: - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsm.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: xs1, vs3 +encoding: + match: 000000101011-----000-----0100111 + variables: + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW = 8; - let EMUL_pow = 0; - let vl_val = unsigned(vl); - let evl : int = if vl_val % 8 == 0 then vl_val / 8 else vl_val / 8 + 1; /* the effective vector length is evl=ceil(vl/8) */ - let num_elem = get_num_elem(EMUL_pow, EEW); - - if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; - - assert(evl >= 0); - process_vm(vd_or_vs3, rs1, num_elem, evl, op) - } +sail(): | + { + let EEW = 8; + let EMUL_pow = 0; + let vl_val = unsigned(vl); + let evl : int = if vl_val % 8 == 0 then vl_val / 8 else vl_val / 8 + 1; /* the effective vector length is evl=ceil(vl/8) */ + let num_elem = get_num_elem(EMUL_pow, EEW); - \ No newline at end of file + if illegal_vd_unmasked() then { handle_illegal(); return RETIRE_FAIL }; + + assert(evl >= 0); + process_vm(vd_or_vs3, rs1, num_elem, evl, op) + } + diff --git a/arch/inst/V/vsmul.vv.yaml b/arch/inst/V/vsmul.vv.yaml index 805431682..f920f1bd3 100644 --- a/arch/inst/V/vsmul.vv.yaml +++ b/arch/inst/V/vsmul.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsmul.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100111-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsmul.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100111-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsmul.vx.yaml b/arch/inst/V/vsmul.vx.yaml index 9db63d425..e0e1e8c37 100644 --- a/arch/inst/V/vsmul.vx.yaml +++ b/arch/inst/V/vsmul.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsmul.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100111-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsmul.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100111-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsoxei16.v.yaml b/arch/inst/V/vsoxei16.v.yaml index 0f0cf3fc9..afd40f9c8 100644 --- a/arch/inst/V/vsoxei16.v.yaml +++ b/arch/inst/V/vsoxei16.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsoxei16.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vs3 - encoding: - match: 000011-----------101-----0100111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsoxei16.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vs3 +encoding: + match: 000011-----------101-----0100111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ - let nf_int = nfields_int(nf); - - if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) + } + diff --git a/arch/inst/V/vsoxei32.v.yaml b/arch/inst/V/vsoxei32.v.yaml index 0f54bbfdd..1c95ac6ce 100644 --- a/arch/inst/V/vsoxei32.v.yaml +++ b/arch/inst/V/vsoxei32.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsoxei32.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vs3 - encoding: - match: 000011-----------110-----0100111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsoxei32.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vs3 +encoding: + match: 000011-----------110-----0100111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ - let nf_int = nfields_int(nf); - - if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) + } + diff --git a/arch/inst/V/vsoxei64.v.yaml b/arch/inst/V/vsoxei64.v.yaml index 832f71870..d53f92437 100644 --- a/arch/inst/V/vsoxei64.v.yaml +++ b/arch/inst/V/vsoxei64.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsoxei64.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vs3 - encoding: - match: 000011-----------111-----0100111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsoxei64.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vs3 +encoding: + match: 000011-----------111-----0100111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ - let nf_int = nfields_int(nf); - - if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) + } + diff --git a/arch/inst/V/vsoxei8.v.yaml b/arch/inst/V/vsoxei8.v.yaml index 60a704ed8..e7aca8d1a 100644 --- a/arch/inst/V/vsoxei8.v.yaml +++ b/arch/inst/V/vsoxei8.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsoxei8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vs3 - encoding: - match: 000011-----------000-----0100111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsoxei8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vs3 +encoding: + match: 000011-----------000-----0100111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ - let nf_int = nfields_int(nf); - - if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) + } + diff --git a/arch/inst/V/vsra.vi.yaml b/arch/inst/V/vsra.vi.yaml index 2265a49ec..0e2ea30cc 100644 --- a/arch/inst/V/vsra.vi.yaml +++ b/arch/inst/V/vsra.vi.yaml @@ -1,94 +1,95 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsra.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 101001-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsra.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 101001-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VADD => vs2_val[i] + imm_val, - VI_VRSUB => imm_val - vs2_val[i], - VI_VAND => vs2_val[i] & imm_val, - VI_VOR => vs2_val[i] | imm_val, - VI_VXOR => vs2_val[i] ^ imm_val, - VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), - VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), - VI_VSLL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] << shift_amount - }, - VI_VSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] >> shift_amount - }, - VI_VSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VI_VSSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VI_VSSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VADD => vs2_val[i] + imm_val, + VI_VRSUB => imm_val - vs2_val[i], + VI_VAND => vs2_val[i] & imm_val, + VI_VOR => vs2_val[i] | imm_val, + VI_VXOR => vs2_val[i] ^ imm_val, + VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), + VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), + VI_VSLL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] << shift_amount + }, + VI_VSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] >> shift_amount + }, + VI_VSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VI_VSSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VI_VSSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsra.vv.yaml b/arch/inst/V/vsra.vv.yaml index 8a19ab5a3..5d2d61969 100644 --- a/arch/inst/V/vsra.vv.yaml +++ b/arch/inst/V/vsra.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsra.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101001-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsra.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101001-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsra.vx.yaml b/arch/inst/V/vsra.vx.yaml index 8a301ac02..f22bc1767 100644 --- a/arch/inst/V/vsra.vx.yaml +++ b/arch/inst/V/vsra.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsra.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101001-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsra.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101001-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsrl.vi.yaml b/arch/inst/V/vsrl.vi.yaml index 2d23c4d3b..5a3bf199b 100644 --- a/arch/inst/V/vsrl.vi.yaml +++ b/arch/inst/V/vsrl.vi.yaml @@ -1,94 +1,95 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsrl.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 101000-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsrl.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 101000-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VADD => vs2_val[i] + imm_val, - VI_VRSUB => imm_val - vs2_val[i], - VI_VAND => vs2_val[i] & imm_val, - VI_VOR => vs2_val[i] | imm_val, - VI_VXOR => vs2_val[i] ^ imm_val, - VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), - VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), - VI_VSLL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] << shift_amount - }, - VI_VSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] >> shift_amount - }, - VI_VSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VI_VSSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VI_VSSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VADD => vs2_val[i] + imm_val, + VI_VRSUB => imm_val - vs2_val[i], + VI_VAND => vs2_val[i] & imm_val, + VI_VOR => vs2_val[i] | imm_val, + VI_VXOR => vs2_val[i] ^ imm_val, + VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), + VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), + VI_VSLL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] << shift_amount + }, + VI_VSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] >> shift_amount + }, + VI_VSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VI_VSSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VI_VSSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsrl.vv.yaml b/arch/inst/V/vsrl.vv.yaml index 7aaa04938..b4414af0a 100644 --- a/arch/inst/V/vsrl.vv.yaml +++ b/arch/inst/V/vsrl.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsrl.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101000-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsrl.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101000-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsrl.vx.yaml b/arch/inst/V/vsrl.vx.yaml index b788358ee..18b4f1837 100644 --- a/arch/inst/V/vsrl.vx.yaml +++ b/arch/inst/V/vsrl.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsrl.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101000-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsrl.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101000-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsse16.v.yaml b/arch/inst/V/vsse16.v.yaml index 8f7e38730..d65aa432b 100644 --- a/arch/inst/V/vsse16.v.yaml +++ b/arch/inst/V/vsse16.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsse16.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs2, xs1, vs3 - encoding: - match: 000010-----------101-----0100111 - variables: - - name: vm - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsse16.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs2, xs1, vs3 +encoding: + match: 000010-----------101-----0100111 + variables: + - name: vm + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vssseg(nf_int, vm, vs3, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vssseg(nf_int, vm, vs3, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vsse32.v.yaml b/arch/inst/V/vsse32.v.yaml index 01a93b23d..782458d9b 100644 --- a/arch/inst/V/vsse32.v.yaml +++ b/arch/inst/V/vsse32.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsse32.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs2, xs1, vs3 - encoding: - match: 000010-----------110-----0100111 - variables: - - name: vm - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsse32.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs2, xs1, vs3 +encoding: + match: 000010-----------110-----0100111 + variables: + - name: vm + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vssseg(nf_int, vm, vs3, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vssseg(nf_int, vm, vs3, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vsse64.v.yaml b/arch/inst/V/vsse64.v.yaml index 0dba178aa..818487762 100644 --- a/arch/inst/V/vsse64.v.yaml +++ b/arch/inst/V/vsse64.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsse64.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs2, xs1, vs3 - encoding: - match: 000010-----------111-----0100111 - variables: - - name: vm - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsse64.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs2, xs1, vs3 +encoding: + match: 000010-----------111-----0100111 + variables: + - name: vm + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vssseg(nf_int, vm, vs3, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vssseg(nf_int, vm, vs3, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vsse8.v.yaml b/arch/inst/V/vsse8.v.yaml index c994bff54..262c0bf44 100644 --- a/arch/inst/V/vsse8.v.yaml +++ b/arch/inst/V/vsse8.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsse8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, xs2, xs1, vs3 - encoding: - match: 000010-----------000-----0100111 - variables: - - name: vm - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsse8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, xs2, xs1, vs3 +encoding: + match: 000010-----------000-----0100111 + variables: + - name: vm + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let load_width_bytes = vlewidth_bytesnumber(width); - let EEW = load_width_bytes * 8; - let EEW_pow = vlewidth_pow(width); - let SEW_pow = get_sew_pow(); - let LMUL_pow = get_lmul_pow(); - let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; - let num_elem = get_num_elem(EMUL_pow, EEW); - let nf_int = nfields_int(nf); - - if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vssseg(nf_int, vm, vs3, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) - } +sail(): | + { + let load_width_bytes = vlewidth_bytesnumber(width); + let EEW = load_width_bytes * 8; + let EEW_pow = vlewidth_pow(width); + let SEW_pow = get_sew_pow(); + let LMUL_pow = get_lmul_pow(); + let EMUL_pow = EEW_pow - SEW_pow + LMUL_pow; + let num_elem = get_num_elem(EMUL_pow, EEW); + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_store(nf_int, EEW, EMUL_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vssseg(nf_int, vm, vs3, load_width_bytes, rs1, rs2, EMUL_pow, num_elem) + } + diff --git a/arch/inst/V/vssra.vi.yaml b/arch/inst/V/vssra.vi.yaml index e6fc4b837..0c662c450 100644 --- a/arch/inst/V/vssra.vi.yaml +++ b/arch/inst/V/vssra.vi.yaml @@ -1,94 +1,95 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vssra.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 101011-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vssra.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 101011-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VADD => vs2_val[i] + imm_val, - VI_VRSUB => imm_val - vs2_val[i], - VI_VAND => vs2_val[i] & imm_val, - VI_VOR => vs2_val[i] | imm_val, - VI_VXOR => vs2_val[i] ^ imm_val, - VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), - VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), - VI_VSLL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] << shift_amount - }, - VI_VSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] >> shift_amount - }, - VI_VSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VI_VSSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VI_VSSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VADD => vs2_val[i] + imm_val, + VI_VRSUB => imm_val - vs2_val[i], + VI_VAND => vs2_val[i] & imm_val, + VI_VOR => vs2_val[i] | imm_val, + VI_VXOR => vs2_val[i] ^ imm_val, + VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), + VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), + VI_VSLL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] << shift_amount + }, + VI_VSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] >> shift_amount + }, + VI_VSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VI_VSSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VI_VSSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vssra.vv.yaml b/arch/inst/V/vssra.vv.yaml index c38ea24f3..7ff2e9f96 100644 --- a/arch/inst/V/vssra.vv.yaml +++ b/arch/inst/V/vssra.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vssra.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101011-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vssra.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101011-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vssra.vx.yaml b/arch/inst/V/vssra.vx.yaml index 6b9153b75..0de7ada82 100644 --- a/arch/inst/V/vssra.vx.yaml +++ b/arch/inst/V/vssra.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vssra.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101011-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vssra.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101011-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vssrl.vi.yaml b/arch/inst/V/vssrl.vi.yaml index 2b3220447..f95b0e46e 100644 --- a/arch/inst/V/vssrl.vi.yaml +++ b/arch/inst/V/vssrl.vi.yaml @@ -1,94 +1,95 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vssrl.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 101010-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vssrl.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 101010-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VADD => vs2_val[i] + imm_val, - VI_VRSUB => imm_val - vs2_val[i], - VI_VAND => vs2_val[i] & imm_val, - VI_VOR => vs2_val[i] | imm_val, - VI_VXOR => vs2_val[i] ^ imm_val, - VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), - VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), - VI_VSLL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] << shift_amount - }, - VI_VSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] >> shift_amount - }, - VI_VSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VI_VSSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VI_VSSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VADD => vs2_val[i] + imm_val, + VI_VRSUB => imm_val - vs2_val[i], + VI_VAND => vs2_val[i] & imm_val, + VI_VOR => vs2_val[i] | imm_val, + VI_VXOR => vs2_val[i] ^ imm_val, + VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), + VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), + VI_VSLL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] << shift_amount + }, + VI_VSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] >> shift_amount + }, + VI_VSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VI_VSSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VI_VSSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vssrl.vv.yaml b/arch/inst/V/vssrl.vv.yaml index d8ac0e520..7ee05c89c 100644 --- a/arch/inst/V/vssrl.vv.yaml +++ b/arch/inst/V/vssrl.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vssrl.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 101010-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vssrl.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 101010-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vssrl.vx.yaml b/arch/inst/V/vssrl.vx.yaml index a61b6916d..34f7ea8ae 100644 --- a/arch/inst/V/vssrl.vx.yaml +++ b/arch/inst/V/vssrl.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vssrl.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 101010-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vssrl.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 101010-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vssub.vv.yaml b/arch/inst/V/vssub.vv.yaml index cc5414087..f714c6895 100644 --- a/arch/inst/V/vssub.vv.yaml +++ b/arch/inst/V/vssub.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vssub.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100011-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vssub.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100011-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vssub.vx.yaml b/arch/inst/V/vssub.vx.yaml index cdf548904..2e0e0e36b 100644 --- a/arch/inst/V/vssub.vx.yaml +++ b/arch/inst/V/vssub.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vssub.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100011-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vssub.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100011-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vssubu.vv.yaml b/arch/inst/V/vssubu.vv.yaml index 66b9135bd..9f65cded2 100644 --- a/arch/inst/V/vssubu.vv.yaml +++ b/arch/inst/V/vssubu.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vssubu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 100010-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vssubu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 100010-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vssubu.vx.yaml b/arch/inst/V/vssubu.vx.yaml index 2bf9501c4..81e4d6b05 100644 --- a/arch/inst/V/vssubu.vx.yaml +++ b/arch/inst/V/vssubu.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vssubu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 100010-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vssubu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 100010-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsub.vv.yaml b/arch/inst/V/vsub.vv.yaml index fabeb4f4c..a257e86d5 100644 --- a/arch/inst/V/vsub.vv.yaml +++ b/arch/inst/V/vsub.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsub.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 000010-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsub.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 000010-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsub.vx.yaml b/arch/inst/V/vsub.vx.yaml index be71c99ae..193e7408d 100644 --- a/arch/inst/V/vsub.vx.yaml +++ b/arch/inst/V/vsub.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsub.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 000010-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsub.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 000010-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vsuxei16.v.yaml b/arch/inst/V/vsuxei16.v.yaml index 19af1fe8d..c9f0b5388 100644 --- a/arch/inst/V/vsuxei16.v.yaml +++ b/arch/inst/V/vsuxei16.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsuxei16.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vs3 - encoding: - match: 000001-----------101-----0100111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsuxei16.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vs3 +encoding: + match: 000001-----------101-----0100111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ - let nf_int = nfields_int(nf); - - if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) + } + diff --git a/arch/inst/V/vsuxei32.v.yaml b/arch/inst/V/vsuxei32.v.yaml index 8b105badc..07c6bc5a8 100644 --- a/arch/inst/V/vsuxei32.v.yaml +++ b/arch/inst/V/vsuxei32.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsuxei32.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vs3 - encoding: - match: 000001-----------110-----0100111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsuxei32.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vs3 +encoding: + match: 000001-----------110-----0100111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ - let nf_int = nfields_int(nf); - - if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) + } + diff --git a/arch/inst/V/vsuxei64.v.yaml b/arch/inst/V/vsuxei64.v.yaml index 2bffa482e..15a59cbc4 100644 --- a/arch/inst/V/vsuxei64.v.yaml +++ b/arch/inst/V/vsuxei64.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsuxei64.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vs3 - encoding: - match: 000001-----------111-----0100111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsuxei64.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vs3 +encoding: + match: 000001-----------111-----0100111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ - let nf_int = nfields_int(nf); - - if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) + } + diff --git a/arch/inst/V/vsuxei8.v.yaml b/arch/inst/V/vsuxei8.v.yaml index 8aa72b111..717c6f4fc 100644 --- a/arch/inst/V/vsuxei8.v.yaml +++ b/arch/inst/V/vsuxei8.v.yaml @@ -1,47 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsuxei8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vs3 - encoding: - match: 000001-----------000-----0100111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vs3 - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsuxei8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vs3 +encoding: + match: 000001-----------000-----0100111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vs3 + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let EEW_index_pow = vlewidth_pow(width); - let EEW_index_bytes = vlewidth_bytesnumber(width); - let EEW_data_pow = get_sew_pow(); - let EEW_data_bytes = get_sew_bytes(); - let EMUL_data_pow = get_lmul_pow(); - let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; - let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ - let nf_int = nfields_int(nf); - - if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; - - process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) - } +sail(): | + { + let EEW_index_pow = vlewidth_pow(width); + let EEW_index_bytes = vlewidth_bytesnumber(width); + let EEW_data_pow = get_sew_pow(); + let EEW_data_bytes = get_sew_bytes(); + let EMUL_data_pow = get_lmul_pow(); + let EMUL_index_pow = EEW_index_pow - EEW_data_pow + EMUL_data_pow; + let num_elem = get_num_elem(EMUL_data_pow, EEW_data_bytes * 8); /* number of data and indices are the same */ + let nf_int = nfields_int(nf); - \ No newline at end of file + if illegal_indexed_store(nf_int, EEW_index_bytes * 8, EMUL_index_pow, EMUL_data_pow) then { handle_illegal(); return RETIRE_FAIL }; + + process_vsxseg(nf_int, vm, vs3, EEW_index_bytes, EEW_data_bytes, EMUL_index_pow, EMUL_data_pow, rs1, vs2, num_elem, 1) + } + diff --git a/arch/inst/V/vwadd.vv.yaml b/arch/inst/V/vwadd.vv.yaml index 8e1b7a8cf..3b237223e 100644 --- a/arch/inst/V/vwadd.vv.yaml +++ b/arch/inst/V/vwadd.vv.yaml @@ -1,76 +1,77 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwadd.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110001-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwadd.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110001-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), - WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), - WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), - WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), - WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), - WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), - WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), + WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), + WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), + WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), + WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), + WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), + WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwadd.vx.yaml b/arch/inst/V/vwadd.vx.yaml index dd7a787dd..ed7378983 100644 --- a/arch/inst/V/vwadd.vx.yaml +++ b/arch/inst/V/vwadd.vx.yaml @@ -1,75 +1,76 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwadd.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 110001-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwadd.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 110001-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), - WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), - WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), - WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), - WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), - WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), - WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), + WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), + WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), + WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), + WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), + WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), + WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwadd.wv.yaml b/arch/inst/V/vwadd.wv.yaml index 30e3eb951..035b42755 100644 --- a/arch/inst/V/vwadd.wv.yaml +++ b/arch/inst/V/vwadd.wv.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwadd.wv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110101-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwadd.wv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110101-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), - WV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), - WV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), - WV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), + WV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), + WV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), + WV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwadd.wx.yaml b/arch/inst/V/vwadd.wx.yaml index 7c1b0b5d9..07a880ebe 100644 --- a/arch/inst/V/vwadd.wx.yaml +++ b/arch/inst/V/vwadd.wx.yaml @@ -1,71 +1,72 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwadd.wx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 110101-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwadd.wx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 110101-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), - WX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), - WX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), - WX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), + WX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), + WX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), + WX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwaddu.vv.yaml b/arch/inst/V/vwaddu.vv.yaml index 4482949c5..e2c393361 100644 --- a/arch/inst/V/vwaddu.vv.yaml +++ b/arch/inst/V/vwaddu.vv.yaml @@ -1,76 +1,77 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwaddu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110000-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwaddu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110000-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), - WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), - WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), - WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), - WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), - WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), - WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), + WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), + WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), + WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), + WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), + WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), + WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwaddu.vx.yaml b/arch/inst/V/vwaddu.vx.yaml index 8e5e95798..cf58098a2 100644 --- a/arch/inst/V/vwaddu.vx.yaml +++ b/arch/inst/V/vwaddu.vx.yaml @@ -1,75 +1,76 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwaddu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 110000-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwaddu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 110000-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), - WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), - WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), - WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), - WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), - WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), - WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), + WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), + WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), + WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), + WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), + WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), + WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwaddu.wv.yaml b/arch/inst/V/vwaddu.wv.yaml index b03e45e83..198b61f01 100644 --- a/arch/inst/V/vwaddu.wv.yaml +++ b/arch/inst/V/vwaddu.wv.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwaddu.wv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110100-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwaddu.wv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110100-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), - WV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), - WV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), - WV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), + WV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), + WV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), + WV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwaddu.wx.yaml b/arch/inst/V/vwaddu.wx.yaml index a08ac63cb..8eb165cdd 100644 --- a/arch/inst/V/vwaddu.wx.yaml +++ b/arch/inst/V/vwaddu.wx.yaml @@ -1,71 +1,72 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwaddu.wx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 110100-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwaddu.wx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 110100-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), - WX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), - WX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), - WX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), + WX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), + WX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), + WX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwmacc.vv.yaml b/arch/inst/V/vwmacc.vv.yaml index 24bde114b..5d41ec9a8 100644 --- a/arch/inst/V/vwmacc.vv.yaml +++ b/arch/inst/V/vwmacc.vv.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwmacc.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 111101-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwmacc.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 111101-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WMVV_VWMACC => to_bits(SEW_widen, signed(vs1_val[i]) * signed(vs2_val[i])) + vd_val[i], - WMVV_VWMACCU => to_bits(SEW_widen, unsigned(vs1_val[i]) * unsigned(vs2_val[i])) + vd_val[i], - WMVV_VWMACCSU => to_bits(SEW_widen, signed(vs1_val[i]) * unsigned(vs2_val[i]))+ vd_val[i] - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WMVV_VWMACC => to_bits(SEW_widen, signed(vs1_val[i]) * signed(vs2_val[i])) + vd_val[i], + WMVV_VWMACCU => to_bits(SEW_widen, unsigned(vs1_val[i]) * unsigned(vs2_val[i])) + vd_val[i], + WMVV_VWMACCSU => to_bits(SEW_widen, signed(vs1_val[i]) * unsigned(vs2_val[i]))+ vd_val[i] } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwmacc.vx.yaml b/arch/inst/V/vwmacc.vx.yaml index 60e0c0932..8f1e04ea9 100644 --- a/arch/inst/V/vwmacc.vx.yaml +++ b/arch/inst/V/vwmacc.vx.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwmacc.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 111101-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwmacc.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 111101-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WMVX_VWMACCU => (to_bits(SEW_widen, unsigned(rs1_val) * unsigned(vs2_val[i]) )) + vd_val[i], - WMVX_VWMACC => (to_bits(SEW_widen, signed(rs1_val) * signed(vs2_val[i]) )) + vd_val[i], - WMVX_VWMACCUS => (to_bits(SEW_widen, unsigned(rs1_val) * signed(vs2_val[i]) ))+ vd_val[i], - WMVX_VWMACCSU => (to_bits(SEW_widen, signed(rs1_val) * unsigned(vs2_val[i]) ))+ vd_val[i] - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WMVX_VWMACCU => (to_bits(SEW_widen, unsigned(rs1_val) * unsigned(vs2_val[i]) )) + vd_val[i], + WMVX_VWMACC => (to_bits(SEW_widen, signed(rs1_val) * signed(vs2_val[i]) )) + vd_val[i], + WMVX_VWMACCUS => (to_bits(SEW_widen, unsigned(rs1_val) * signed(vs2_val[i]) ))+ vd_val[i], + WMVX_VWMACCSU => (to_bits(SEW_widen, signed(rs1_val) * unsigned(vs2_val[i]) ))+ vd_val[i] } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwmaccsu.vv.yaml b/arch/inst/V/vwmaccsu.vv.yaml index 4f4c99896..a635909f9 100644 --- a/arch/inst/V/vwmaccsu.vv.yaml +++ b/arch/inst/V/vwmaccsu.vv.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwmaccsu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 111111-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwmaccsu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 111111-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WMVV_VWMACC => to_bits(SEW_widen, signed(vs1_val[i]) * signed(vs2_val[i])) + vd_val[i], - WMVV_VWMACCU => to_bits(SEW_widen, unsigned(vs1_val[i]) * unsigned(vs2_val[i])) + vd_val[i], - WMVV_VWMACCSU => to_bits(SEW_widen, signed(vs1_val[i]) * unsigned(vs2_val[i]))+ vd_val[i] - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WMVV_VWMACC => to_bits(SEW_widen, signed(vs1_val[i]) * signed(vs2_val[i])) + vd_val[i], + WMVV_VWMACCU => to_bits(SEW_widen, unsigned(vs1_val[i]) * unsigned(vs2_val[i])) + vd_val[i], + WMVV_VWMACCSU => to_bits(SEW_widen, signed(vs1_val[i]) * unsigned(vs2_val[i]))+ vd_val[i] } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwmaccsu.vx.yaml b/arch/inst/V/vwmaccsu.vx.yaml index d75326a2b..36901bbac 100644 --- a/arch/inst/V/vwmaccsu.vx.yaml +++ b/arch/inst/V/vwmaccsu.vx.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwmaccsu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 111111-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwmaccsu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 111111-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WMVX_VWMACCU => (to_bits(SEW_widen, unsigned(rs1_val) * unsigned(vs2_val[i]) )) + vd_val[i], - WMVX_VWMACC => (to_bits(SEW_widen, signed(rs1_val) * signed(vs2_val[i]) )) + vd_val[i], - WMVX_VWMACCUS => (to_bits(SEW_widen, unsigned(rs1_val) * signed(vs2_val[i]) ))+ vd_val[i], - WMVX_VWMACCSU => (to_bits(SEW_widen, signed(rs1_val) * unsigned(vs2_val[i]) ))+ vd_val[i] - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WMVX_VWMACCU => (to_bits(SEW_widen, unsigned(rs1_val) * unsigned(vs2_val[i]) )) + vd_val[i], + WMVX_VWMACC => (to_bits(SEW_widen, signed(rs1_val) * signed(vs2_val[i]) )) + vd_val[i], + WMVX_VWMACCUS => (to_bits(SEW_widen, unsigned(rs1_val) * signed(vs2_val[i]) ))+ vd_val[i], + WMVX_VWMACCSU => (to_bits(SEW_widen, signed(rs1_val) * unsigned(vs2_val[i]) ))+ vd_val[i] } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwmaccu.vv.yaml b/arch/inst/V/vwmaccu.vv.yaml index 376850524..57612798b 100644 --- a/arch/inst/V/vwmaccu.vv.yaml +++ b/arch/inst/V/vwmaccu.vv.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwmaccu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 111100-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwmaccu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 111100-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WMVV_VWMACC => to_bits(SEW_widen, signed(vs1_val[i]) * signed(vs2_val[i])) + vd_val[i], - WMVV_VWMACCU => to_bits(SEW_widen, unsigned(vs1_val[i]) * unsigned(vs2_val[i])) + vd_val[i], - WMVV_VWMACCSU => to_bits(SEW_widen, signed(vs1_val[i]) * unsigned(vs2_val[i]))+ vd_val[i] - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WMVV_VWMACC => to_bits(SEW_widen, signed(vs1_val[i]) * signed(vs2_val[i])) + vd_val[i], + WMVV_VWMACCU => to_bits(SEW_widen, unsigned(vs1_val[i]) * unsigned(vs2_val[i])) + vd_val[i], + WMVV_VWMACCSU => to_bits(SEW_widen, signed(vs1_val[i]) * unsigned(vs2_val[i]))+ vd_val[i] } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwmaccu.vx.yaml b/arch/inst/V/vwmaccu.vx.yaml index ecc080ba2..edf144908 100644 --- a/arch/inst/V/vwmaccu.vx.yaml +++ b/arch/inst/V/vwmaccu.vx.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwmaccu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 111100-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwmaccu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 111100-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WMVX_VWMACCU => (to_bits(SEW_widen, unsigned(rs1_val) * unsigned(vs2_val[i]) )) + vd_val[i], - WMVX_VWMACC => (to_bits(SEW_widen, signed(rs1_val) * signed(vs2_val[i]) )) + vd_val[i], - WMVX_VWMACCUS => (to_bits(SEW_widen, unsigned(rs1_val) * signed(vs2_val[i]) ))+ vd_val[i], - WMVX_VWMACCSU => (to_bits(SEW_widen, signed(rs1_val) * unsigned(vs2_val[i]) ))+ vd_val[i] - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WMVX_VWMACCU => (to_bits(SEW_widen, unsigned(rs1_val) * unsigned(vs2_val[i]) )) + vd_val[i], + WMVX_VWMACC => (to_bits(SEW_widen, signed(rs1_val) * signed(vs2_val[i]) )) + vd_val[i], + WMVX_VWMACCUS => (to_bits(SEW_widen, unsigned(rs1_val) * signed(vs2_val[i]) ))+ vd_val[i], + WMVX_VWMACCSU => (to_bits(SEW_widen, signed(rs1_val) * unsigned(vs2_val[i]) ))+ vd_val[i] } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwmaccus.vx.yaml b/arch/inst/V/vwmaccus.vx.yaml index eeaa64340..0e3070929 100644 --- a/arch/inst/V/vwmaccus.vx.yaml +++ b/arch/inst/V/vwmaccus.vx.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwmaccus.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 111110-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwmaccus.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 111110-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WMVX_VWMACCU => (to_bits(SEW_widen, unsigned(rs1_val) * unsigned(vs2_val[i]) )) + vd_val[i], - WMVX_VWMACC => (to_bits(SEW_widen, signed(rs1_val) * signed(vs2_val[i]) )) + vd_val[i], - WMVX_VWMACCUS => (to_bits(SEW_widen, unsigned(rs1_val) * signed(vs2_val[i]) ))+ vd_val[i], - WMVX_VWMACCSU => (to_bits(SEW_widen, signed(rs1_val) * unsigned(vs2_val[i]) ))+ vd_val[i] - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WMVX_VWMACCU => (to_bits(SEW_widen, unsigned(rs1_val) * unsigned(vs2_val[i]) )) + vd_val[i], + WMVX_VWMACC => (to_bits(SEW_widen, signed(rs1_val) * signed(vs2_val[i]) )) + vd_val[i], + WMVX_VWMACCUS => (to_bits(SEW_widen, unsigned(rs1_val) * signed(vs2_val[i]) ))+ vd_val[i], + WMVX_VWMACCSU => (to_bits(SEW_widen, signed(rs1_val) * unsigned(vs2_val[i]) ))+ vd_val[i] } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwmul.vv.yaml b/arch/inst/V/vwmul.vv.yaml index bdd7f476d..a32fda5df 100644 --- a/arch/inst/V/vwmul.vv.yaml +++ b/arch/inst/V/vwmul.vv.yaml @@ -1,76 +1,77 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwmul.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 111011-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwmul.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 111011-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), - WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), - WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), - WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), - WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), - WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), - WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), + WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), + WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), + WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), + WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), + WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), + WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwmul.vx.yaml b/arch/inst/V/vwmul.vx.yaml index 341138dd3..5dc3c3d25 100644 --- a/arch/inst/V/vwmul.vx.yaml +++ b/arch/inst/V/vwmul.vx.yaml @@ -1,75 +1,76 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwmul.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 111011-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwmul.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 111011-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), - WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), - WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), - WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), - WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), - WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), - WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), + WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), + WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), + WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), + WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), + WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), + WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwmulsu.vv.yaml b/arch/inst/V/vwmulsu.vv.yaml index 300d934dd..d7ee5d18d 100644 --- a/arch/inst/V/vwmulsu.vv.yaml +++ b/arch/inst/V/vwmulsu.vv.yaml @@ -1,76 +1,77 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwmulsu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 111010-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwmulsu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 111010-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), - WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), - WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), - WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), - WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), - WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), - WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), + WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), + WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), + WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), + WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), + WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), + WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwmulsu.vx.yaml b/arch/inst/V/vwmulsu.vx.yaml index a65c44d50..4bc0ea6f9 100644 --- a/arch/inst/V/vwmulsu.vx.yaml +++ b/arch/inst/V/vwmulsu.vx.yaml @@ -1,75 +1,76 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwmulsu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 111010-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwmulsu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 111010-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), - WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), - WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), - WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), - WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), - WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), - WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), + WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), + WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), + WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), + WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), + WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), + WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwmulu.vv.yaml b/arch/inst/V/vwmulu.vv.yaml index 7a8b3b527..1d157720d 100644 --- a/arch/inst/V/vwmulu.vv.yaml +++ b/arch/inst/V/vwmulu.vv.yaml @@ -1,76 +1,77 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwmulu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 111000-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwmulu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 111000-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), - WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), - WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), - WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), - WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), - WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), - WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), + WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), + WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), + WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), + WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), + WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), + WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwmulu.vx.yaml b/arch/inst/V/vwmulu.vx.yaml index d7002afb3..191102861 100644 --- a/arch/inst/V/vwmulu.vx.yaml +++ b/arch/inst/V/vwmulu.vx.yaml @@ -1,75 +1,76 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwmulu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 111000-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwmulu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 111000-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), - WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), - WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), - WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), - WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), - WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), - WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), + WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), + WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), + WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), + WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), + WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), + WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwredsum.vs.yaml b/arch/inst/V/vwredsum.vs.yaml index 53b2b9176..869c4fbef 100644 --- a/arch/inst/V/vwredsum.vs.yaml +++ b/arch/inst/V/vwredsum.vs.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwredsum.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110001-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwredsum.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110001-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - let num_elem_vd = get_num_elem(0, SEW_widen); /* vd regardless of LMUL setting */ - - if illegal_reduction_widen(SEW_widen, LMUL_pow_widen) then { handle_illegal(); return RETIRE_FAIL }; - - if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ - - let 'n = num_elem_vs; - let 'd = num_elem_vd; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); - let vd_val : vector('d, dec, bits('o)) = read_vreg(num_elem_vd, SEW_widen, 0, vd); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); - let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); - - sum : bits('o) = read_single_element(SEW_widen, 0, vs1); /* vs1 regardless of LMUL setting */ - foreach (i from 0 to (num_elem_vs - 1)) { - if mask[i] then { - let elem : bits('o) = match funct6 { - IVV_VWREDSUMU => to_bits(SEW_widen, unsigned(vs2_val[i])), - IVV_VWREDSUM => to_bits(SEW_widen, signed(vs2_val[i])) - }; - sum = sum + elem - } - }; - - write_single_element(SEW_widen, 0, vd, sum); - /* other elements in vd are treated as tail elements, currently remain unchanged */ - /* TODO: configuration support for agnostic behavior */ - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + let num_elem_vs = get_num_elem(LMUL_pow, SEW); + let num_elem_vd = get_num_elem(0, SEW_widen); /* vd regardless of LMUL setting */ - \ No newline at end of file + if illegal_reduction_widen(SEW_widen, LMUL_pow_widen) then { handle_illegal(); return RETIRE_FAIL }; + + if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ + + let 'n = num_elem_vs; + let 'd = num_elem_vd; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); + let vd_val : vector('d, dec, bits('o)) = read_vreg(num_elem_vd, SEW_widen, 0, vd); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); + let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); + + sum : bits('o) = read_single_element(SEW_widen, 0, vs1); /* vs1 regardless of LMUL setting */ + foreach (i from 0 to (num_elem_vs - 1)) { + if mask[i] then { + let elem : bits('o) = match funct6 { + IVV_VWREDSUMU => to_bits(SEW_widen, unsigned(vs2_val[i])), + IVV_VWREDSUM => to_bits(SEW_widen, signed(vs2_val[i])) + }; + sum = sum + elem + } + }; + + write_single_element(SEW_widen, 0, vd, sum); + /* other elements in vd are treated as tail elements, currently remain unchanged */ + /* TODO: configuration support for agnostic behavior */ + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwredsumu.vs.yaml b/arch/inst/V/vwredsumu.vs.yaml index fc5bbb5ed..d3739d187 100644 --- a/arch/inst/V/vwredsumu.vs.yaml +++ b/arch/inst/V/vwredsumu.vs.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwredsumu.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110000-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwredsumu.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110000-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - let num_elem_vs = get_num_elem(LMUL_pow, SEW); - let num_elem_vd = get_num_elem(0, SEW_widen); /* vd regardless of LMUL setting */ - - if illegal_reduction_widen(SEW_widen, LMUL_pow_widen) then { handle_illegal(); return RETIRE_FAIL }; - - if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ - - let 'n = num_elem_vs; - let 'd = num_elem_vd; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); - let vd_val : vector('d, dec, bits('o)) = read_vreg(num_elem_vd, SEW_widen, 0, vd); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); - let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); - - sum : bits('o) = read_single_element(SEW_widen, 0, vs1); /* vs1 regardless of LMUL setting */ - foreach (i from 0 to (num_elem_vs - 1)) { - if mask[i] then { - let elem : bits('o) = match funct6 { - IVV_VWREDSUMU => to_bits(SEW_widen, unsigned(vs2_val[i])), - IVV_VWREDSUM => to_bits(SEW_widen, signed(vs2_val[i])) - }; - sum = sum + elem - } - }; - - write_single_element(SEW_widen, 0, vd, sum); - /* other elements in vd are treated as tail elements, currently remain unchanged */ - /* TODO: configuration support for agnostic behavior */ - vstart = zeros(); - RETIRE_SUCCESS - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + let num_elem_vs = get_num_elem(LMUL_pow, SEW); + let num_elem_vd = get_num_elem(0, SEW_widen); /* vd regardless of LMUL setting */ - \ No newline at end of file + if illegal_reduction_widen(SEW_widen, LMUL_pow_widen) then { handle_illegal(); return RETIRE_FAIL }; + + if unsigned(vl) == 0 then return RETIRE_SUCCESS; /* if vl=0, no operation is performed */ + + let 'n = num_elem_vs; + let 'd = num_elem_vd; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem_vs, vm, 0b00000); + let vd_val : vector('d, dec, bits('o)) = read_vreg(num_elem_vd, SEW_widen, 0, vd); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem_vs, SEW, LMUL_pow, vs2); + let mask : vector('n, dec, bool) = init_masked_source(num_elem_vs, LMUL_pow, vm_val); + + sum : bits('o) = read_single_element(SEW_widen, 0, vs1); /* vs1 regardless of LMUL setting */ + foreach (i from 0 to (num_elem_vs - 1)) { + if mask[i] then { + let elem : bits('o) = match funct6 { + IVV_VWREDSUMU => to_bits(SEW_widen, unsigned(vs2_val[i])), + IVV_VWREDSUM => to_bits(SEW_widen, signed(vs2_val[i])) + }; + sum = sum + elem + } + }; + + write_single_element(SEW_widen, 0, vd, sum); + /* other elements in vd are treated as tail elements, currently remain unchanged */ + /* TODO: configuration support for agnostic behavior */ + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwsub.vv.yaml b/arch/inst/V/vwsub.vv.yaml index 81d3ee13e..def690ade 100644 --- a/arch/inst/V/vwsub.vv.yaml +++ b/arch/inst/V/vwsub.vv.yaml @@ -1,76 +1,77 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwsub.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110011-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwsub.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110011-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), - WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), - WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), - WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), - WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), - WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), - WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), + WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), + WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), + WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), + WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), + WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), + WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwsub.vx.yaml b/arch/inst/V/vwsub.vx.yaml index ef60087ff..037a57975 100644 --- a/arch/inst/V/vwsub.vx.yaml +++ b/arch/inst/V/vwsub.vx.yaml @@ -1,75 +1,76 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwsub.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 110011-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwsub.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 110011-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), - WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), - WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), - WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), - WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), - WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), - WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), + WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), + WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), + WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), + WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), + WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), + WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwsub.wv.yaml b/arch/inst/V/vwsub.wv.yaml index 0fd993451..d295bd785 100644 --- a/arch/inst/V/vwsub.wv.yaml +++ b/arch/inst/V/vwsub.wv.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwsub.wv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110111-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwsub.wv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110111-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), - WV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), - WV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), - WV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), + WV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), + WV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), + WV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwsub.wx.yaml b/arch/inst/V/vwsub.wx.yaml index 710c4562b..76b836b67 100644 --- a/arch/inst/V/vwsub.wx.yaml +++ b/arch/inst/V/vwsub.wx.yaml @@ -1,71 +1,72 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwsub.wx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 110111-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwsub.wx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 110111-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), - WX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), - WX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), - WX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), + WX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), + WX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), + WX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwsubu.vv.yaml b/arch/inst/V/vwsubu.vv.yaml index 04b6b1ac4..c2b5c8eb0 100644 --- a/arch/inst/V/vwsubu.vv.yaml +++ b/arch/inst/V/vwsubu.vv.yaml @@ -1,76 +1,77 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwsubu.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110010-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwsubu.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110010-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), - WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), - WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), - WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), - WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), - WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), - WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), + WVV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), + WVV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), + WVV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])), + WVV_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(vs1_val[i])), + WVV_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(vs1_val[i])), + WVV_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwsubu.vx.yaml b/arch/inst/V/vwsubu.vx.yaml index a9b3c699f..d70695bb2 100644 --- a/arch/inst/V/vwsubu.vx.yaml +++ b/arch/inst/V/vwsubu.vx.yaml @@ -1,75 +1,76 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwsubu.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 110010-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwsubu.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 110010-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), - WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), - WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), - WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), - WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), - WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), - WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs2, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WVX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), + WVX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), + WVX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), + WVX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)), + WVX_VWMUL => to_bits(SEW_widen, signed(vs2_val[i]) * signed(rs1_val)), + WVX_VWMULU => to_bits(SEW_widen, unsigned(vs2_val[i]) * unsigned(rs1_val)), + WVX_VWMULSU => to_bits(SEW_widen, signed(vs2_val[i]) * unsigned(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwsubu.wv.yaml b/arch/inst/V/vwsubu.wv.yaml index f34fb40ef..5da6b8f10 100644 --- a/arch/inst/V/vwsubu.wv.yaml +++ b/arch/inst/V/vwsubu.wv.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwsubu.wv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 110110-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwsubu.wv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 110110-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | - not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), - WV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), - WV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), - WV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) | + not(valid_reg_overlap(vs1, vd, LMUL_pow, LMUL_pow_widen)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WV_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(vs1_val[i])), + WV_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(vs1_val[i])), + WV_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(vs1_val[i])), + WV_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(vs1_val[i])) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vwsubu.wx.yaml b/arch/inst/V/vwsubu.wx.yaml index 564d4df86..3aab9d1b1 100644 --- a/arch/inst/V/vwsubu.wx.yaml +++ b/arch/inst/V/vwsubu.wx.yaml @@ -1,71 +1,72 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwsubu.wx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 110110-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwsubu.wx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 110110-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_widen = SEW * 2; - let LMUL_pow_widen = LMUL_pow + 1; - - if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_widen; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); - result : vector('n, dec, bits('o)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - WX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), - WX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), - WX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), - WX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_widen = SEW * 2; + let LMUL_pow_widen = LMUL_pow + 1; + + if illegal_variable_width(vd, vm, SEW_widen, LMUL_pow_widen) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_widen; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_widen, LMUL_pow_widen, vs2); + result : vector('n, dec, bits('o)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW_widen, LMUL_pow_widen, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + WX_VADD => to_bits(SEW_widen, signed(vs2_val[i]) + signed(rs1_val)), + WX_VSUB => to_bits(SEW_widen, signed(vs2_val[i]) - signed(rs1_val)), + WX_VADDU => to_bits(SEW_widen, unsigned(vs2_val[i]) + unsigned(rs1_val)), + WX_VSUBU => to_bits(SEW_widen, unsigned(vs2_val[i]) - unsigned(rs1_val)) } - }; - - write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW_widen, LMUL_pow_widen, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vxor.vi.yaml b/arch/inst/V/vxor.vi.yaml index c552c2872..9f1e02491 100644 --- a/arch/inst/V/vxor.vi.yaml +++ b/arch/inst/V/vxor.vi.yaml @@ -1,94 +1,95 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vxor.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd, imm - encoding: - match: 001011-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: simm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vxor.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd, imm +encoding: + match: 001011-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: simm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let imm_val : bits('m) = sign_extend(simm); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VI_VADD => vs2_val[i] + imm_val, - VI_VRSUB => imm_val - vs2_val[i], - VI_VAND => vs2_val[i] & imm_val, - VI_VOR => vs2_val[i] | imm_val, - VI_VXOR => vs2_val[i] ^ imm_val, - VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), - VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), - VI_VSLL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] << shift_amount - }, - VI_VSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - vs2_val[i] >> shift_amount - }, - VI_VSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VI_VSSRL => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VI_VSSRA => { - let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - } - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let imm_val : bits('m) = sign_extend(simm); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VI_VADD => vs2_val[i] + imm_val, + VI_VRSUB => imm_val - vs2_val[i], + VI_VAND => vs2_val[i] & imm_val, + VI_VOR => vs2_val[i] | imm_val, + VI_VXOR => vs2_val[i] ^ imm_val, + VI_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, imm_val) ), + VI_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, imm_val) ), + VI_VSLL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] << shift_amount + }, + VI_VSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + vs2_val[i] >> shift_amount + }, + VI_VSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VI_VSSRL => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VI_VSSRA => { + let shift_amount = get_shift_amount(zero_extend('m, simm), SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vxor.vv.yaml b/arch/inst/V/vxor.vv.yaml index b7c008f02..32f05d9f8 100644 --- a/arch/inst/V/vxor.vv.yaml +++ b/arch/inst/V/vxor.vv.yaml @@ -1,127 +1,128 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vxor.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vs1, vd - encoding: - match: 001011-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vxor.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vs1, vd +encoding: + match: 001011-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW_pow = get_sew_pow(); - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let VLEN_pow = get_vlen_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VV_VADD => vs2_val[i] + vs1_val[i], - VV_VSUB => vs2_val[i] - vs1_val[i], - VV_VAND => vs2_val[i] & vs1_val[i], - VV_VOR => vs2_val[i] | vs1_val[i], - VV_VXOR => vs2_val[i] ^ vs1_val[i], - VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), - VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), - VV_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) - }, - VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), - VV_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VV_VSLL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] << shift_amount - }, - VV_VSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - vs2_val[i] >> shift_amount - }, - VV_VSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VV_VSSRL => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VV_VSSRA => { - let shift_amount = get_shift_amount(vs1_val[i], SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), - VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), - VV_VRGATHER => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - let idx = unsigned(vs1_val[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - }, - VV_VRGATHEREI16 => { - if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; - /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ - let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); - let idx = unsigned(vs1_new[i]); - let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); - assert(VLMAX <= 'n); - if idx < VLMAX then vs2_val[idx] else zeros() - } - } +sail(): | + { + let SEW_pow = get_sew_pow(); + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let VLEN_pow = get_vlen_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VV_VADD => vs2_val[i] + vs1_val[i], + VV_VSUB => vs2_val[i] - vs1_val[i], + VV_VAND => vs2_val[i] & vs1_val[i], + VV_VOR => vs2_val[i] | vs1_val[i], + VV_VXOR => vs2_val[i] ^ vs1_val[i], + VV_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, vs1_val[i])), + VV_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, vs1_val[i])), + VV_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(vs1_val[i]) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, vs1_val[i])) + }, + VV_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, vs1_val[i])), + VV_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(vs1_val[i])); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VV_VSLL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] << shift_amount + }, + VV_VSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + vs2_val[i] >> shift_amount + }, + VV_VSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VV_VSSRL => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VV_VSSRA => { + let shift_amount = get_shift_amount(vs1_val[i], SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VV_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(vs1_val[i]))), + VV_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(vs1_val[i]))), + VV_VRGATHER => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + let idx = unsigned(vs1_val[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + }, + VV_VRGATHEREI16 => { + if (vs1 == vd | vs2 == vd) then { handle_illegal(); return RETIRE_FAIL }; + /* vrgatherei16.vv uses SEW/LMUL for the data in vs2 but EEW=16 and EMUL = (16/SEW)*LMUL for the indices in vs1 */ + let vs1_new : vector('n, dec, bits(16)) = read_vreg(num_elem, 16, 4 + LMUL_pow - SEW_pow, vs1); + let idx = unsigned(vs1_new[i]); + let VLMAX = int_power(2, LMUL_pow + VLEN_pow - SEW_pow); + assert(VLMAX <= 'n); + if idx < VLMAX then vs2_val[idx] else zeros() + } } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vxor.vx.yaml b/arch/inst/V/vxor.vx.yaml index 25a62e254..405e521ed 100644 --- a/arch/inst/V/vxor.vx.yaml +++ b/arch/inst/V/vxor.vx.yaml @@ -1,110 +1,111 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vxor.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, xs1, vd - encoding: - match: 001011-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vxor.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, xs1, vd +encoding: + match: 001011-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - - if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let rs1_val : bits('m) = get_scalar(rs1, SEW); - let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VX_VADD => vs2_val[i] + rs1_val, - VX_VSUB => vs2_val[i] - rs1_val, - VX_VRSUB => rs1_val - vs2_val[i], - VX_VAND => vs2_val[i] & rs1_val, - VX_VOR => vs2_val[i] | rs1_val, - VX_VXOR => vs2_val[i] ^ rs1_val, - VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), - VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), - VX_VSSUBU => { - if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() - else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) - }, - VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), - VX_VSMUL => { - let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); - let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); - let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); - signed_saturation('m, result_wide['m..0]) - }, - VX_VSLL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] << shift_amount - }, - VX_VSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - vs2_val[i] >> shift_amount - }, - VX_VSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) - }, - VX_VSSRL => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) - }, - VX_VSSRA => { - let shift_amount = get_shift_amount(rs1_val, SEW); - let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); - let v_double : bits('m * 2) = sign_extend(vs2_val[i]); - slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) - }, - VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), - VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), - VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + + if illegal_normal(vd, vm) then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let rs1_val : bits('m) = get_scalar(rs1, SEW); + let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VX_VADD => vs2_val[i] + rs1_val, + VX_VSUB => vs2_val[i] - rs1_val, + VX_VRSUB => rs1_val - vs2_val[i], + VX_VAND => vs2_val[i] & rs1_val, + VX_VOR => vs2_val[i] | rs1_val, + VX_VXOR => vs2_val[i] ^ rs1_val, + VX_VSADDU => unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) + zero_extend('m + 1, rs1_val) ), + VX_VSADD => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) + sign_extend('m + 1, rs1_val) ), + VX_VSSUBU => { + if unsigned(vs2_val[i]) < unsigned(rs1_val) then zeros() + else unsigned_saturation('m, zero_extend('m + 1, vs2_val[i]) - zero_extend('m + 1, rs1_val) ) + }, + VX_VSSUB => signed_saturation('m, sign_extend('m + 1, vs2_val[i]) - sign_extend('m + 1, rs1_val) ), + VX_VSMUL => { + let result_mul = to_bits('m * 2, signed(vs2_val[i]) * signed(rs1_val)); + let rounding_incr = get_fixed_rounding_incr(result_mul, 'm - 1); + let result_wide = (result_mul >> ('m - 1)) + zero_extend('m * 2, rounding_incr); + signed_saturation('m, result_wide['m..0]) + }, + VX_VSLL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] << shift_amount + }, + VX_VSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + vs2_val[i] >> shift_amount + }, + VX_VSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + }, + VX_VSSRL => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + (vs2_val[i] >> shift_amount) + zero_extend('m, rounding_incr) + }, + VX_VSSRA => { + let shift_amount = get_shift_amount(rs1_val, SEW); + let rounding_incr = get_fixed_rounding_incr(vs2_val[i], shift_amount); + let v_double : bits('m * 2) = sign_extend(vs2_val[i]); + slice(v_double >> shift_amount, 0, SEW) + zero_extend('m, rounding_incr) + }, + VX_VMINU => to_bits(SEW, min(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMIN => to_bits(SEW, min(signed(vs2_val[i]), signed(rs1_val))), + VX_VMAXU => to_bits(SEW, max(unsigned(vs2_val[i]), unsigned(rs1_val))), + VX_VMAX => to_bits(SEW, max(signed(vs2_val[i]), signed(rs1_val))) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vzext.vf2.yaml b/arch/inst/V/vzext.vf2.yaml index 65aa0deec..f3ef6b579 100644 --- a/arch/inst/V/vzext.vf2.yaml +++ b/arch/inst/V/vzext.vf2.yaml @@ -1,68 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vzext.vf2: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------00110010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vzext.vf2 +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------00110010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_half = SEW / 2; - let LMUL_pow_half = LMUL_pow - 1; - - if illegal_variable_width(vd, vm, SEW_half, LMUL_pow_half) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_half, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_half; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_half, LMUL_pow_half, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW > SEW_half); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VEXT2_ZVF2 => zero_extend(vs2_val[i]), - VEXT2_SVF2 => sign_extend(vs2_val[i]) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_half = SEW / 2; + let LMUL_pow_half = LMUL_pow - 1; + + if illegal_variable_width(vd, vm, SEW_half, LMUL_pow_half) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_half, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_half; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_half, LMUL_pow_half, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW > SEW_half); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VEXT2_ZVF2 => zero_extend(vs2_val[i]), + VEXT2_SVF2 => sign_extend(vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vzext.vf4.yaml b/arch/inst/V/vzext.vf4.yaml index 4ae4120d0..70832f506 100644 --- a/arch/inst/V/vzext.vf4.yaml +++ b/arch/inst/V/vzext.vf4.yaml @@ -1,68 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vzext.vf4: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------00100010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vzext.vf4 +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------00100010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_quart = SEW / 4; - let LMUL_pow_quart = LMUL_pow - 2; - - if illegal_variable_width(vd, vm, SEW_quart, LMUL_pow_quart) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_quart, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_quart; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_quart, LMUL_pow_quart, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW > SEW_quart); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VEXT4_ZVF4 => zero_extend(vs2_val[i]), - VEXT4_SVF4 => sign_extend(vs2_val[i]) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_quart = SEW / 4; + let LMUL_pow_quart = LMUL_pow - 2; + + if illegal_variable_width(vd, vm, SEW_quart, LMUL_pow_quart) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_quart, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_quart; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_quart, LMUL_pow_quart, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW > SEW_quart); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VEXT4_ZVF4 => zero_extend(vs2_val[i]), + VEXT4_SVF4 => sign_extend(vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/V/vzext.vf8.yaml b/arch/inst/V/vzext.vf8.yaml index 584373a9c..8e0fb1c88 100644 --- a/arch/inst/V/vzext.vf8.yaml +++ b/arch/inst/V/vzext.vf8.yaml @@ -1,68 +1,69 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vzext.vf8: - long_name: No synopsis available. - description: | - No description available. - definedBy: V - assembly: vm, vs2, vd - encoding: - match: 010010------00010010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vzext.vf8 +long_name: No synopsis available. +description: | + No description available. +definedBy: V +assembly: vm, vs2, vd +encoding: + match: 010010------00010010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let SEW = get_sew(); - let LMUL_pow = get_lmul_pow(); - let num_elem = get_num_elem(LMUL_pow, SEW); - let SEW_eighth = SEW / 8; - let LMUL_pow_eighth = LMUL_pow - 3; - - if illegal_variable_width(vd, vm, SEW_eighth, LMUL_pow_eighth) | - not(valid_reg_overlap(vs2, vd, LMUL_pow_eighth, LMUL_pow)) - then { handle_illegal(); return RETIRE_FAIL }; - - let 'n = num_elem; - let 'm = SEW; - let 'o = SEW_eighth; - - let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); - let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); - let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_eighth, LMUL_pow_eighth, vs2); - result : vector('n, dec, bits('m)) = undefined; - mask : vector('n, dec, bool) = undefined; - - (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); - - assert(SEW > SEW_eighth); - foreach (i from 0 to (num_elem - 1)) { - if mask[i] then { - result[i] = match funct6 { - VEXT8_ZVF8 => zero_extend(vs2_val[i]), - VEXT8_SVF8 => sign_extend(vs2_val[i]) - } +sail(): | + { + let SEW = get_sew(); + let LMUL_pow = get_lmul_pow(); + let num_elem = get_num_elem(LMUL_pow, SEW); + let SEW_eighth = SEW / 8; + let LMUL_pow_eighth = LMUL_pow - 3; + + if illegal_variable_width(vd, vm, SEW_eighth, LMUL_pow_eighth) | + not(valid_reg_overlap(vs2, vd, LMUL_pow_eighth, LMUL_pow)) + then { handle_illegal(); return RETIRE_FAIL }; + + let 'n = num_elem; + let 'm = SEW; + let 'o = SEW_eighth; + + let vm_val : vector('n, dec, bool) = read_vmask(num_elem, vm, 0b00000); + let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); + let vs2_val : vector('n, dec, bits('o)) = read_vreg(num_elem, SEW_eighth, LMUL_pow_eighth, vs2); + result : vector('n, dec, bits('m)) = undefined; + mask : vector('n, dec, bool) = undefined; + + (result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val); + + assert(SEW > SEW_eighth); + foreach (i from 0 to (num_elem - 1)) { + if mask[i] then { + result[i] = match funct6 { + VEXT8_ZVF8 => zero_extend(vs2_val[i]), + VEXT8_SVF8 => sign_extend(vs2_val[i]) } - }; - - write_vreg(num_elem, SEW, LMUL_pow, vd, result); - vstart = zeros(); - RETIRE_SUCCESS - } + } + }; - \ No newline at end of file + write_vreg(num_elem, SEW, LMUL_pow, vd, result); + vstart = zeros(); + RETIRE_SUCCESS + } + diff --git a/arch/inst/Zabha/amoadd.b.yaml b/arch/inst/Zabha/amoadd.b.yaml index 4e0c46d6b..5024808c2 100644 --- a/arch/inst/Zabha/amoadd.b.yaml +++ b/arch/inst/Zabha/amoadd.b.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoadd.b: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 00000------------000-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.b +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 00000------------000-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amoadd.b: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amoadd.h.yaml b/arch/inst/Zabha/amoadd.h.yaml index eaecfc8b3..07ef0b18f 100644 --- a/arch/inst/Zabha/amoadd.h.yaml +++ b/arch/inst/Zabha/amoadd.h.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoadd.h: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 00000------------001-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.h +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 00000------------001-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amoadd.h: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amoand.b.yaml b/arch/inst/Zabha/amoand.b.yaml index 2fe971a45..abb64cf26 100644 --- a/arch/inst/Zabha/amoand.b.yaml +++ b/arch/inst/Zabha/amoand.b.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoand.b: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 01100------------000-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amoand.b +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 01100------------000-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amoand.b: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amoand.h.yaml b/arch/inst/Zabha/amoand.h.yaml index 0d45a5e3a..dd21970bb 100644 --- a/arch/inst/Zabha/amoand.h.yaml +++ b/arch/inst/Zabha/amoand.h.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoand.h: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 01100------------001-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amoand.h +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 01100------------001-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amoand.h: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amocas.b.yaml b/arch/inst/Zabha/amocas.b.yaml index e30b22918..a54fff572 100644 --- a/arch/inst/Zabha/amocas.b.yaml +++ b/arch/inst/Zabha/amocas.b.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amocas.b: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 00101------------000-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amocas.b +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 00101------------000-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zabha/amocas.h.yaml b/arch/inst/Zabha/amocas.h.yaml index 74df0fcc9..7406e4a4f 100644 --- a/arch/inst/Zabha/amocas.h.yaml +++ b/arch/inst/Zabha/amocas.h.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amocas.h: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 00101------------001-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amocas.h +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 00101------------001-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zabha/amomax.b.yaml b/arch/inst/Zabha/amomax.b.yaml index ab0271dbe..bb49fc9f3 100644 --- a/arch/inst/Zabha/amomax.b.yaml +++ b/arch/inst/Zabha/amomax.b.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amomax.b: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 10100------------000-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amomax.b +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 10100------------000-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amomax.b: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amomax.h.yaml b/arch/inst/Zabha/amomax.h.yaml index 5fbdd9fab..e89c043a5 100644 --- a/arch/inst/Zabha/amomax.h.yaml +++ b/arch/inst/Zabha/amomax.h.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amomax.h: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 10100------------001-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amomax.h +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 10100------------001-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amomax.h: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amomaxu.b.yaml b/arch/inst/Zabha/amomaxu.b.yaml index c8b5fe267..5cde35d5d 100644 --- a/arch/inst/Zabha/amomaxu.b.yaml +++ b/arch/inst/Zabha/amomaxu.b.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amomaxu.b: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 11100------------000-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.b +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 11100------------000-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amomaxu.b: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amomaxu.h.yaml b/arch/inst/Zabha/amomaxu.h.yaml index b3206cbe3..ea6538fb5 100644 --- a/arch/inst/Zabha/amomaxu.h.yaml +++ b/arch/inst/Zabha/amomaxu.h.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amomaxu.h: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 11100------------001-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.h +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 11100------------001-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amomaxu.h: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amomin.b.yaml b/arch/inst/Zabha/amomin.b.yaml index ee1ab2fcd..bba1d9afe 100644 --- a/arch/inst/Zabha/amomin.b.yaml +++ b/arch/inst/Zabha/amomin.b.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amomin.b: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 10000------------000-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amomin.b +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 10000------------000-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amomin.b: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amomin.h.yaml b/arch/inst/Zabha/amomin.h.yaml index b9d58d251..71164e406 100644 --- a/arch/inst/Zabha/amomin.h.yaml +++ b/arch/inst/Zabha/amomin.h.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amomin.h: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 10000------------001-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amomin.h +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 10000------------001-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amomin.h: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amominu.b.yaml b/arch/inst/Zabha/amominu.b.yaml index cea2e1b6f..1ec23a812 100644 --- a/arch/inst/Zabha/amominu.b.yaml +++ b/arch/inst/Zabha/amominu.b.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amominu.b: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 11000------------000-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amominu.b +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 11000------------000-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amominu.b: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amominu.h.yaml b/arch/inst/Zabha/amominu.h.yaml index e4adb78a7..be68c5947 100644 --- a/arch/inst/Zabha/amominu.h.yaml +++ b/arch/inst/Zabha/amominu.h.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amominu.h: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 11000------------001-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amominu.h +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 11000------------001-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amominu.h: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amoor.b.yaml b/arch/inst/Zabha/amoor.b.yaml index 1c899e42a..7fc285824 100644 --- a/arch/inst/Zabha/amoor.b.yaml +++ b/arch/inst/Zabha/amoor.b.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoor.b: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 01000------------000-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amoor.b +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 01000------------000-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amoor.b: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amoor.h.yaml b/arch/inst/Zabha/amoor.h.yaml index adc4226d6..85d3a704d 100644 --- a/arch/inst/Zabha/amoor.h.yaml +++ b/arch/inst/Zabha/amoor.h.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoor.h: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 01000------------001-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amoor.h +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 01000------------001-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amoor.h: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amoswap.b.yaml b/arch/inst/Zabha/amoswap.b.yaml index f5404270b..68d63647e 100644 --- a/arch/inst/Zabha/amoswap.b.yaml +++ b/arch/inst/Zabha/amoswap.b.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoswap.b: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 00001------------000-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.b +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 00001------------000-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amoswap.b: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amoswap.h.yaml b/arch/inst/Zabha/amoswap.h.yaml index bede3da58..76cf8d38a 100644 --- a/arch/inst/Zabha/amoswap.h.yaml +++ b/arch/inst/Zabha/amoswap.h.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoswap.h: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 00001------------001-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.h +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 00001------------001-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amoswap.h: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amoxor.b.yaml b/arch/inst/Zabha/amoxor.b.yaml index 8ec5bae68..ba29559e2 100644 --- a/arch/inst/Zabha/amoxor.b.yaml +++ b/arch/inst/Zabha/amoxor.b.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoxor.b: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 00100------------000-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.b +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 00100------------000-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amoxor.b: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zabha/amoxor.h.yaml b/arch/inst/Zabha/amoxor.h.yaml index e4cbe9240..3017d2291 100644 --- a/arch/inst/Zabha/amoxor.h.yaml +++ b/arch/inst/Zabha/amoxor.h.yaml @@ -1,112 +1,113 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amoxor.h: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zabha - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 00100------------001-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.h +long_name: No synopsis available. +description: | + No description available. +definedBy: Zabha +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 00100------------001-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - if extension("A") then { - /* Get the address, X(rs1) (no offset). - * Some extensions perform additional checks on address validity. - */ - match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => { - match translateAddr(vaddr, ReadWrite(Data, Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - let is_unsigned : bool = match op { - AMOMINU => true, - AMOMAXU => true, - _ => false - }; - let rs2_val : xlenbits = match width { - BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), - HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), - WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), - DOUBLE => X(rs2) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") - }; - match (mval) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(loaded) => { - let result : xlenbits = - match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, - - /* These operations convert bitvectors to integer values using [un]signed, - * and back using to_bits(). - */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) - }; - let rval : xlenbits = match width { - BYTE => sign_extend(loaded[7..0]), - HALF => sign_extend(loaded[15..0]), - WORD => sign_extend(loaded[31..0]), - DOUBLE => loaded - }; - let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), - _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) }; - match (wval) { - MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, - MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } @@ -115,10 +116,10 @@ amoxor.h: } } } - } else { - handle_illegal(); - RETIRE_FAIL } + } else { + handle_illegal(); + RETIRE_FAIL } - - \ No newline at end of file + } + diff --git a/arch/inst/Zacas/amocas.d.yaml b/arch/inst/Zacas/amocas.d.yaml index 0066cd98a..8b7dfe167 100644 --- a/arch/inst/Zacas/amocas.d.yaml +++ b/arch/inst/Zacas/amocas.d.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amocas.d: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zacas - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 00101------------011-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amocas.d +long_name: No synopsis available. +description: | + No description available. +definedBy: Zacas +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 00101------------011-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zacas/amocas.q.yaml b/arch/inst/Zacas/amocas.q.yaml index 9ac04094e..63fa46f73 100644 --- a/arch/inst/Zacas/amocas.q.yaml +++ b/arch/inst/Zacas/amocas.q.yaml @@ -1,30 +1,32 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amocas.q: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zacas - base: 64 - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 00101------------100-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amocas.q +long_name: No synopsis available. +description: | + No description available. +definedBy: Zacas +base: 64 +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 00101------------100-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zacas/amocas.w.yaml b/arch/inst/Zacas/amocas.w.yaml index 902768dfa..0e64eccde 100644 --- a/arch/inst/Zacas/amocas.w.yaml +++ b/arch/inst/Zacas/amocas.w.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -amocas.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zacas - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 00101------------010-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: amocas.w +long_name: No synopsis available. +description: | + No description available. +definedBy: Zacas +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 00101------------010-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zalasr/lb.aq.yaml b/arch/inst/Zalasr/lb.aq.yaml index 6a616c7ab..8b649b935 100644 --- a/arch/inst/Zalasr/lb.aq.yaml +++ b/arch/inst/Zalasr/lb.aq.yaml @@ -1,57 +1,58 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -lb.aq: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zalasr - assembly: xd, xs1, rl - encoding: - match: 001101-00000-----000-----0101111 - variables: - - name: rl - location: 25-25 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: lb.aq +long_name: No synopsis available. +description: | + No description available. +definedBy: Zalasr +assembly: xd, xs1, rl +encoding: + match: 001101-00000-----000-----0101111 + variables: + - name: rl + location: 25-25 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => - match (width) { - BYTE => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), - HALF => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), - WORD => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), - DOUBLE if sizeof(xlen) >= 64 => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), - _ => report_invalid_width(__FILE__, __LINE__, width, "load") - } - } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } } - - \ No newline at end of file + } + diff --git a/arch/inst/Zalasr/ld.aq.yaml b/arch/inst/Zalasr/ld.aq.yaml index 6bba1cab9..90a37dad1 100644 --- a/arch/inst/Zalasr/ld.aq.yaml +++ b/arch/inst/Zalasr/ld.aq.yaml @@ -1,57 +1,58 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -ld.aq: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zalasr - assembly: xd, xs1, rl - encoding: - match: 001101-00000-----011-----0101111 - variables: - - name: rl - location: 25-25 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: ld.aq +long_name: No synopsis available. +description: | + No description available. +definedBy: Zalasr +assembly: xd, xs1, rl +encoding: + match: 001101-00000-----011-----0101111 + variables: + - name: rl + location: 25-25 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => - match (width) { - BYTE => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), - HALF => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), - WORD => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), - DOUBLE if sizeof(xlen) >= 64 => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), - _ => report_invalid_width(__FILE__, __LINE__, width, "load") - } - } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } } - - \ No newline at end of file + } + diff --git a/arch/inst/Zalasr/lh.aq.yaml b/arch/inst/Zalasr/lh.aq.yaml index 6de5df42c..9d3a81213 100644 --- a/arch/inst/Zalasr/lh.aq.yaml +++ b/arch/inst/Zalasr/lh.aq.yaml @@ -1,57 +1,58 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -lh.aq: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zalasr - assembly: xd, xs1, rl - encoding: - match: 001101-00000-----001-----0101111 - variables: - - name: rl - location: 25-25 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: lh.aq +long_name: No synopsis available. +description: | + No description available. +definedBy: Zalasr +assembly: xd, xs1, rl +encoding: + match: 001101-00000-----001-----0101111 + variables: + - name: rl + location: 25-25 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => - match (width) { - BYTE => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), - HALF => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), - WORD => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), - DOUBLE if sizeof(xlen) >= 64 => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), - _ => report_invalid_width(__FILE__, __LINE__, width, "load") - } - } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } } - - \ No newline at end of file + } + diff --git a/arch/inst/Zalasr/lw.aq.yaml b/arch/inst/Zalasr/lw.aq.yaml index f11af4587..65a5435e4 100644 --- a/arch/inst/Zalasr/lw.aq.yaml +++ b/arch/inst/Zalasr/lw.aq.yaml @@ -1,57 +1,58 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -lw.aq: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zalasr - assembly: xd, xs1, rl - encoding: - match: 001101-00000-----010-----0101111 - variables: - - name: rl - location: 25-25 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: lw.aq +long_name: No synopsis available. +description: | + No description available. +definedBy: Zalasr +assembly: xd, xs1, rl +encoding: + match: 001101-00000-----010-----0101111 + variables: + - name: rl + location: 25-25 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => - match (width) { - BYTE => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), - HALF => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), - WORD => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), - DOUBLE if sizeof(xlen) >= 64 => - process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), - _ => report_invalid_width(__FILE__, __LINE__, width, "load") - } - } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } } - - \ No newline at end of file + } + diff --git a/arch/inst/Zalasr/sb.rl.yaml b/arch/inst/Zalasr/sb.rl.yaml index 526d291f5..19b6fd35a 100644 --- a/arch/inst/Zalasr/sb.rl.yaml +++ b/arch/inst/Zalasr/sb.rl.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sb.rl: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zalasr - assembly: xs1, xs2, aq - encoding: - match: 00111-1----------000000000101111 - variables: - - name: aq - location: 26-26 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sb.rl +long_name: No synopsis available. +description: | + No description available. +definedBy: Zalasr +assembly: xs1, xs2, aq +encoding: + match: 00111-1----------000000000101111 + variables: + - name: aq + location: 26-26 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Write(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Write(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => { - let eares : MemoryOpResult(unit) = match width { - BYTE => mem_write_ea(paddr, 1, aq, rl, false), - HALF => mem_write_ea(paddr, 2, aq, rl, false), - WORD => mem_write_ea(paddr, 4, aq, rl, false), - DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let rs2_val = X(rs2); - let res : MemoryOpResult(bool) = match (width) { - BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), - HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), - WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), - DOUBLE if sizeof(xlen) >= 64 - => mem_write_value(paddr, 8, rs2_val, aq, rl, false), - _ => report_invalid_width(__FILE__, __LINE__, width, "store"), - }; - match (res) { - MemValue(true) => RETIRE_SUCCESS, - MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Write(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Write(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => { + let eares : MemoryOpResult(unit) = match width { + BYTE => mem_write_ea(paddr, 1, aq, rl, false), + HALF => mem_write_ea(paddr, 2, aq, rl, false), + WORD => mem_write_ea(paddr, 4, aq, rl, false), + DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let rs2_val = X(rs2); + let res : MemoryOpResult(bool) = match (width) { + BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), + HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), + WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), + DOUBLE if sizeof(xlen) >= 64 + => mem_write_value(paddr, 8, rs2_val, aq, rl, false), + _ => report_invalid_width(__FILE__, __LINE__, width, "store"), + }; + match (res) { + MemValue(true) => RETIRE_SUCCESS, + MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } } - } + } } - - \ No newline at end of file + } + diff --git a/arch/inst/Zalasr/sd.rl.yaml b/arch/inst/Zalasr/sd.rl.yaml index 0f737532e..49af9816b 100644 --- a/arch/inst/Zalasr/sd.rl.yaml +++ b/arch/inst/Zalasr/sd.rl.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sd.rl: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zalasr - assembly: xs1, xs2, aq - encoding: - match: 00111-1----------011000000101111 - variables: - - name: aq - location: 26-26 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sd.rl +long_name: No synopsis available. +description: | + No description available. +definedBy: Zalasr +assembly: xs1, xs2, aq +encoding: + match: 00111-1----------011000000101111 + variables: + - name: aq + location: 26-26 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Write(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Write(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => { - let eares : MemoryOpResult(unit) = match width { - BYTE => mem_write_ea(paddr, 1, aq, rl, false), - HALF => mem_write_ea(paddr, 2, aq, rl, false), - WORD => mem_write_ea(paddr, 4, aq, rl, false), - DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let rs2_val = X(rs2); - let res : MemoryOpResult(bool) = match (width) { - BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), - HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), - WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), - DOUBLE if sizeof(xlen) >= 64 - => mem_write_value(paddr, 8, rs2_val, aq, rl, false), - _ => report_invalid_width(__FILE__, __LINE__, width, "store"), - }; - match (res) { - MemValue(true) => RETIRE_SUCCESS, - MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Write(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Write(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => { + let eares : MemoryOpResult(unit) = match width { + BYTE => mem_write_ea(paddr, 1, aq, rl, false), + HALF => mem_write_ea(paddr, 2, aq, rl, false), + WORD => mem_write_ea(paddr, 4, aq, rl, false), + DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let rs2_val = X(rs2); + let res : MemoryOpResult(bool) = match (width) { + BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), + HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), + WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), + DOUBLE if sizeof(xlen) >= 64 + => mem_write_value(paddr, 8, rs2_val, aq, rl, false), + _ => report_invalid_width(__FILE__, __LINE__, width, "store"), + }; + match (res) { + MemValue(true) => RETIRE_SUCCESS, + MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } } - } + } } - - \ No newline at end of file + } + diff --git a/arch/inst/Zalasr/sh.rl.yaml b/arch/inst/Zalasr/sh.rl.yaml index 006356943..d28714762 100644 --- a/arch/inst/Zalasr/sh.rl.yaml +++ b/arch/inst/Zalasr/sh.rl.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sh.rl: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zalasr - assembly: xs1, xs2, aq - encoding: - match: 00111-1----------001000000101111 - variables: - - name: aq - location: 26-26 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sh.rl +long_name: No synopsis available. +description: | + No description available. +definedBy: Zalasr +assembly: xs1, xs2, aq +encoding: + match: 00111-1----------001000000101111 + variables: + - name: aq + location: 26-26 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Write(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Write(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => { - let eares : MemoryOpResult(unit) = match width { - BYTE => mem_write_ea(paddr, 1, aq, rl, false), - HALF => mem_write_ea(paddr, 2, aq, rl, false), - WORD => mem_write_ea(paddr, 4, aq, rl, false), - DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let rs2_val = X(rs2); - let res : MemoryOpResult(bool) = match (width) { - BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), - HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), - WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), - DOUBLE if sizeof(xlen) >= 64 - => mem_write_value(paddr, 8, rs2_val, aq, rl, false), - _ => report_invalid_width(__FILE__, __LINE__, width, "store"), - }; - match (res) { - MemValue(true) => RETIRE_SUCCESS, - MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Write(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Write(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => { + let eares : MemoryOpResult(unit) = match width { + BYTE => mem_write_ea(paddr, 1, aq, rl, false), + HALF => mem_write_ea(paddr, 2, aq, rl, false), + WORD => mem_write_ea(paddr, 4, aq, rl, false), + DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let rs2_val = X(rs2); + let res : MemoryOpResult(bool) = match (width) { + BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), + HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), + WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), + DOUBLE if sizeof(xlen) >= 64 + => mem_write_value(paddr, 8, rs2_val, aq, rl, false), + _ => report_invalid_width(__FILE__, __LINE__, width, "store"), + }; + match (res) { + MemValue(true) => RETIRE_SUCCESS, + MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } } - } + } } - - \ No newline at end of file + } + diff --git a/arch/inst/Zalasr/sw.rl.yaml b/arch/inst/Zalasr/sw.rl.yaml index 0f8ddfe17..48535507b 100644 --- a/arch/inst/Zalasr/sw.rl.yaml +++ b/arch/inst/Zalasr/sw.rl.yaml @@ -1,72 +1,73 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sw.rl: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zalasr - assembly: xs1, xs2, aq - encoding: - match: 00111-1----------010000000101111 - variables: - - name: aq - location: 26-26 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sw.rl +long_name: No synopsis available. +description: | + No description available. +definedBy: Zalasr +assembly: xs1, xs2, aq +encoding: + match: 00111-1----------010000000101111 + variables: + - name: aq + location: 26-26 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Write(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Write(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(paddr, _) => { - let eares : MemoryOpResult(unit) = match width { - BYTE => mem_write_ea(paddr, 1, aq, rl, false), - HALF => mem_write_ea(paddr, 2, aq, rl, false), - WORD => mem_write_ea(paddr, 4, aq, rl, false), - DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let rs2_val = X(rs2); - let res : MemoryOpResult(bool) = match (width) { - BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), - HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), - WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), - DOUBLE if sizeof(xlen) >= 64 - => mem_write_value(paddr, 8, rs2_val, aq, rl, false), - _ => report_invalid_width(__FILE__, __LINE__, width, "store"), - }; - match (res) { - MemValue(true) => RETIRE_SUCCESS, - MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Write(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Write(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => { + let eares : MemoryOpResult(unit) = match width { + BYTE => mem_write_ea(paddr, 1, aq, rl, false), + HALF => mem_write_ea(paddr, 2, aq, rl, false), + WORD => mem_write_ea(paddr, 4, aq, rl, false), + DOUBLE => mem_write_ea(paddr, 8, aq, rl, false) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let rs2_val = X(rs2); + let res : MemoryOpResult(bool) = match (width) { + BYTE => mem_write_value(paddr, 1, rs2_val[7..0], aq, rl, false), + HALF => mem_write_value(paddr, 2, rs2_val[15..0], aq, rl, false), + WORD => mem_write_value(paddr, 4, rs2_val[31..0], aq, rl, false), + DOUBLE if sizeof(xlen) >= 64 + => mem_write_value(paddr, 8, rs2_val, aq, rl, false), + _ => report_invalid_width(__FILE__, __LINE__, width, "store"), + }; + match (res) { + MemValue(true) => RETIRE_SUCCESS, + MemValue(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"), + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } } } } } - } + } } - - \ No newline at end of file + } + diff --git a/arch/inst/Zawrs/wrs.nto.yaml b/arch/inst/Zawrs/wrs.nto.yaml index cccd2583a..4c130ba85 100644 --- a/arch/inst/Zawrs/wrs.nto.yaml +++ b/arch/inst/Zawrs/wrs.nto.yaml @@ -1,19 +1,21 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -wrs.nto: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zawrs - assembly: wrs_nto - encoding: - match: '00000000110100000000000001110011' - variables: [] - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: wrs.nto +long_name: No synopsis available. +description: | + No description available. +definedBy: Zawrs +assembly: wrs_nto +encoding: + match: '00000000110100000000000001110011' + variables: [] +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zawrs/wrs.sto.yaml b/arch/inst/Zawrs/wrs.sto.yaml index b03bbcd57..d623a43ea 100644 --- a/arch/inst/Zawrs/wrs.sto.yaml +++ b/arch/inst/Zawrs/wrs.sto.yaml @@ -1,19 +1,21 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -wrs.sto: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zawrs - assembly: wrs_sto - encoding: - match: '00000001110100000000000001110011' - variables: [] - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: wrs.sto +long_name: No synopsis available. +description: | + No description available. +definedBy: Zawrs +assembly: wrs_sto +encoding: + match: '00000001110100000000000001110011' + variables: [] +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zfbfmin/fcvt.bf16.s.yaml b/arch/inst/Zfbfmin/fcvt.bf16.s.yaml index a6ecf80f1..9d31847a5 100644 --- a/arch/inst/Zfbfmin/fcvt.bf16.s.yaml +++ b/arch/inst/Zfbfmin/fcvt.bf16.s.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.bf16.s: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zfbfmin - assembly: xd, xs1, rm - encoding: - match: 010001001000-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.bf16.s +long_name: No synopsis available. +description: | + No description available. +definedBy: Zfbfmin +assembly: xd, xs1, rm +encoding: + match: 010001001000-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zfbfmin/fcvt.s.bf16.yaml b/arch/inst/Zfbfmin/fcvt.s.bf16.yaml index ec48f5e56..70af2004a 100644 --- a/arch/inst/Zfbfmin/fcvt.s.bf16.yaml +++ b/arch/inst/Zfbfmin/fcvt.s.bf16.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.s.bf16: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zfbfmin - assembly: xd, xs1, rm - encoding: - match: 010000000110-------------1010011 - variables: - - name: rs1 - location: 19-15 - - name: rm - location: 14-12 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.s.bf16 +long_name: No synopsis available. +description: | + No description available. +definedBy: Zfbfmin +assembly: xd, xs1, rm +encoding: + match: 010000000110-------------1010011 + variables: + - name: rs1 + location: 19-15 + - name: rm + location: 14-12 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zfh/fcvt.h.s.yaml b/arch/inst/Zfh/fcvt.h.s.yaml index ac5b65a91..808ef24b6 100644 --- a/arch/inst/Zfh/fcvt.h.s.yaml +++ b/arch/inst/Zfh/fcvt.h.s.yaml @@ -1,87 +1,89 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.h.s: - long_name: Convert half-precision float to a single-precision float - definedBy: - anyOf: [Zfh, Zfhmin] - assembly: fd, xs1 - description: | - Converts a half-precision number in floating-point register _fs1_ into a single-precision floating-point number in - floating-point register _fd_. +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.h.s +long_name: Convert half-precision float to a single-precision float +definedBy: + anyOf: [Zfh, Zfhmin] +assembly: fd, xs1 +description: | + Converts a half-precision number in floating-point register _fs1_ into a single-precision floating-point number in + floating-point register _fd_. - `fcvt.h.s` rounds according to the _rm_ field. + `fcvt.h.s` rounds according to the _rm_ field. - All floating-point conversion instructions set the Inexact exception flag if the rounded - result differs from the operand value and the Invalid exception flag is not set. + All floating-point conversion instructions set the Inexact exception flag if the rounded + result differs from the operand value and the Invalid exception flag is not set. - encoding: - match: 010001000000-------------1010011 - variables: - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - check_f_ok($encoding); +encoding: + match: 010001000000-------------1010011 + variables: + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + check_f_ok($encoding); - Bits<16> hp_value = f[fs1][15:0]; + Bits<16> hp_value = f[fs1][15:0]; - Bits<1> sign = hp_value[15]; - Bits<5> exp = hp_value[14:10]; - Bits<10> frac = hp_value[9:0]; + Bits<1> sign = hp_value[15]; + Bits<5> exp = hp_value[14:10]; + Bits<10> frac = hp_value[9:0]; - if (exp == 0x1F) { - if (frac != 0) { - if ((hp_value & 0x0200) != 0) { - set_fp_flag(FpFlag::NV); - } - f[fd] = HP_CANONICAL_NAN; - } else { - f[fd] = packToF32UI(sign, 0xFF, 0); + if (exp == 0x1F) { + if (frac != 0) { + if ((hp_value & 0x0200) != 0) { + set_fp_flag(FpFlag::NV); } + f[fd] = HP_CANONICAL_NAN; } else { - if (exp != 0) { - if (frac != 0) { - f[fd] = packToF32UI(sign, 0, 0); - } else { - Bits<6> norm_exp; - (norm_exp, frac) = softfloat_normSubnormalF16Sig( frac ); - exp = norm_exp - 1; - f[fd] = packToF32UI(sign, exp + 0x70, frac << 13); - } + f[fd] = packToF32UI(sign, 0xFF, 0); + } + } else { + if (exp != 0) { + if (frac != 0) { + f[fd] = packToF32UI(sign, 0, 0); } else { + Bits<6> norm_exp; + (norm_exp, frac) = softfloat_normSubnormalF16Sig( frac ); + exp = norm_exp - 1; f[fd] = packToF32UI(sign, exp + 0x70, frac << 13); } + } else { + f[fd] = packToF32UI(sign, exp + 0x70, frac << 13); } + } - mark_f_state_dirty(); + mark_f_state_dirty(); - sail(): | - { - assert(sizeof(xlen) >= 64); - let rs1_val_LU = X(rs1)[63..0]; - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_H) = riscv_ui64ToF16 (rm_3b, rs1_val_LU); - - accrue_fflags(fflags); - F_or_X_H(rd) = rd_val_H; - RETIRE_SUCCESS - } +sail(): | + { + assert(sizeof(xlen) >= 64); + let rs1_val_LU = X(rs1)[63..0]; + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_H) = riscv_ui64ToF16 (rm_3b, rs1_val_LU); + + accrue_fflags(fflags); + F_or_X_H(rd) = rd_val_H; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/Zfh/fcvt.s.h.yaml b/arch/inst/Zfh/fcvt.s.h.yaml index c974fbbb5..9ebd1fe1d 100644 --- a/arch/inst/Zfh/fcvt.s.h.yaml +++ b/arch/inst/Zfh/fcvt.s.h.yaml @@ -1,84 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fcvt.s.h: - long_name: Convert single-precision float to a half-precision float - definedBy: - anyOf: [Zfh, Zfhmin] - assembly: fd, xs1 - description: | - Converts a single-precision number in floating-point register _fs1_ into a half-precision floating-point number in - floating-point register _fd_. - - `fcvt.s.h` will never round, and so the 'rm' field is effectively ignored. - - encoding: - match: 010000000010-------------1010011 - variables: - - name: fs1 - location: 19-15 - - name: rm - location: 14-12 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - check_f_ok($encoding); - - Bits<32> sp_value = f[fs1][31:0]; - - Bits<1> sign = sp_value[31]; - Bits<8> exp = sp_value[30:23]; - Bits<23> frac = sp_value[22:0]; - - if (exp == 0xFF) { - if (frac != 0) { - if ((sp_value & 0x00400000) != 0) { - set_fp_flag(FpFlag::NV); - } - f[fd] = nan_box<16, FLEN>(HP_CANONICAL_NAN); - } else { - f[fd] = nan_box<16, FLEN>(packToF16UI( sign, 0x1F, 0 )); - } - } else { +$schema: "inst_schema.json#" +kind: instruction +name: fcvt.s.h +long_name: Convert single-precision float to a half-precision float +definedBy: + anyOf: [Zfh, Zfhmin] +assembly: fd, xs1 +description: | + Converts a single-precision number in floating-point register _fs1_ into a half-precision floating-point number in + floating-point register _fd_. + + `fcvt.s.h` will never round, and so the 'rm' field is effectively ignored. + +encoding: + match: 010000000010-------------1010011 + variables: + - name: fs1 + location: 19-15 + - name: rm + location: 14-12 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + check_f_ok($encoding); - # frac is a 24-bit significand, the bottom 9 bits LSB are extracted and OR-red - # into a sticky flag, the top 15 MSBs are extracted, the LSB of this top slice - # is OR-red with the sticky - Bits<16> frac16 = (frac >> 9) | ((frac & 0x1ff) != 0 ? 1 : 0); - if ((exp | frac16) == 0) { - f[fd] = nan_box<16, FLEN>(packToF16UI( sign, 0, 0 )); - } else { - assert(false, "TODO: implement roundPackToF16"); - # f[fd] = soffloat_roundPackToF16(sign, exp - 0x71, frac16 | 0x4000); + Bits<32> sp_value = f[fs1][31:0]; + + Bits<1> sign = sp_value[31]; + Bits<8> exp = sp_value[30:23]; + Bits<23> frac = sp_value[22:0]; + + if (exp == 0xFF) { + if (frac != 0) { + if ((sp_value & 0x00400000) != 0) { + set_fp_flag(FpFlag::NV); } + f[fd] = nan_box<16, FLEN>(HP_CANONICAL_NAN); + } else { + f[fd] = nan_box<16, FLEN>(packToF16UI( sign, 0x1F, 0 )); + } + } else { + # frac is a 24-bit significand, the bottom 9 bits LSB are extracted and OR-red + # into a sticky flag, the top 15 MSBs are extracted, the LSB of this top slice + # is OR-red with the sticky + Bits<16> frac16 = (frac >> 9) | ((frac & 0x1ff) != 0 ? 1 : 0); + if ((exp | frac16) == 0) { + f[fd] = nan_box<16, FLEN>(packToF16UI( sign, 0, 0 )); + } else { + assert(false, "TODO: implement roundPackToF16"); + # f[fd] = soffloat_roundPackToF16(sign, exp - 0x71, frac16 | 0x4000); } - mark_f_state_dirty(); + } + + mark_f_state_dirty(); - sail(): | - { - assert(sizeof(xlen) >= 64); - let rs1_val_LU = X(rs1)[63..0]; - match (select_instr_or_fcsr_rm (rm)) { - None() => { handle_illegal(); RETIRE_FAIL }, - Some(rm') => { - let rm_3b = encdec_rounding_mode(rm'); - let (fflags, rd_val_H) = riscv_ui64ToF16 (rm_3b, rs1_val_LU); - - accrue_fflags(fflags); - F_or_X_H(rd) = rd_val_H; - RETIRE_SUCCESS - } +sail(): | + { + assert(sizeof(xlen) >= 64); + let rs1_val_LU = X(rs1)[63..0]; + match (select_instr_or_fcsr_rm (rm)) { + None() => { handle_illegal(); RETIRE_FAIL }, + Some(rm') => { + let rm_3b = encdec_rounding_mode(rm'); + let (fflags, rd_val_H) = riscv_ui64ToF16 (rm_3b, rs1_val_LU); + + accrue_fflags(fflags); + F_or_X_H(rd) = rd_val_H; + RETIRE_SUCCESS } } - - + } + + diff --git a/arch/inst/Zfh/flh.yaml b/arch/inst/Zfh/flh.yaml index 359476ba4..5a25dc1da 100644 --- a/arch/inst/Zfh/flh.yaml +++ b/arch/inst/Zfh/flh.yaml @@ -1,73 +1,75 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -flh: - long_name: Half-precision floating-point load - description: | - The `flh` instruction loads a single-precision floating-point value from memory at address _rs1_ + _imm_ into floating-point register _rd_. +$schema: "inst_schema.json#" +kind: instruction +name: flh +long_name: Half-precision floating-point load +description: | + The `flh` instruction loads a single-precision floating-point value from memory at address _rs1_ + _imm_ into floating-point register _rd_. - `flh` does not modify the bits being transferred; in particular, the payloads of non-canonical NaNs are preserved. + `flh` does not modify the bits being transferred; in particular, the payloads of non-canonical NaNs are preserved. - `flh` is only guaranteed to execute atomically if the effective address is naturally aligned. + `flh` is only guaranteed to execute atomically if the effective address is naturally aligned. - definedBy: - anyOf: [Zfh, Zfhmin] - assembly: fd, imm(xs1) - encoding: - match: -----------------001-----0000111 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - check_f_ok($encoding); +definedBy: + anyOf: [Zfh, Zfhmin] +assembly: fd, imm(xs1) +encoding: + match: -----------------001-----0000111 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + check_f_ok($encoding); - XReg virtual_address = X[rs1] + $signed(imm); + XReg virtual_address = X[rs1] + $signed(imm); - Bits<16> hp_value = read_memory<16>(virtual_address, $encoding); + Bits<16> hp_value = read_memory<16>(virtual_address, $encoding); - f[fd] = nan_box<16, FLEN>(hp_value); + f[fd] = nan_box<16, FLEN>(hp_value); - mark_f_state_dirty(); + mark_f_state_dirty(); - sail(): | - { - let offset : xlenbits = sign_extend(imm); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Read(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Read(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let (aq, rl, res) = (false, false, false); - match (width) { - BYTE => { handle_illegal(); RETIRE_FAIL }, - HALF => - process_fload16(rd, vaddr, mem_read(Read(Data), addr, 2, aq, rl, res)), - WORD => - process_fload32(rd, vaddr, mem_read(Read(Data), addr, 4, aq, rl, res)), - DOUBLE if sizeof(flen) >= 64 => - process_fload64(rd, vaddr, mem_read(Read(Data), addr, 8, aq, rl, res)), - _ => report_invalid_width(__FILE__, __LINE__, width, "floating point load"), - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let (aq, rl, res) = (false, false, false); + match (width) { + BYTE => { handle_illegal(); RETIRE_FAIL }, + HALF => + process_fload16(rd, vaddr, mem_read(Read(Data), addr, 2, aq, rl, res)), + WORD => + process_fload32(rd, vaddr, mem_read(Read(Data), addr, 4, aq, rl, res)), + DOUBLE if sizeof(flen) >= 64 => + process_fload64(rd, vaddr, mem_read(Read(Data), addr, 8, aq, rl, res)), + _ => report_invalid_width(__FILE__, __LINE__, width, "floating point load"), } } - } + } } - - + } + + diff --git a/arch/inst/Zfh/fmv.h.x.yaml b/arch/inst/Zfh/fmv.h.x.yaml index b5f9fbca6..701e871f4 100644 --- a/arch/inst/Zfh/fmv.h.x.yaml +++ b/arch/inst/Zfh/fmv.h.x.yaml @@ -1,44 +1,46 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmv.h.x: - long_name: Half-precision floating-point move from integer - description: | - Moves the half-precision value encoded in IEEE 754-2008 standard encoding - from the lower 16 bits of integer register `rs1` to the floating-point - register `fd`. The bits are not modified in the transfer, and in particular, - the payloads of non-canonical NaNs are preserved. - definedBy: F - assembly: fd, xs1 - encoding: - match: 111101000000-----000-----1010011 - variables: - - name: rs1 - location: 19-15 - - name: fd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - check_f_ok($encoding); - - Bits<16> hp_value = X[rs1][15:0]; - - f[fd] = nan_box<16, FLEN>(hp_value); - - mark_f_state_dirty(); - - - sail(): | - { - let rs1_val_X = X(rs1); - let rd_val_H = rs1_val_X [15..0]; - F(rd) = nan_box (rd_val_H); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: fmv.h.x +long_name: Half-precision floating-point move from integer +description: | + Moves the half-precision value encoded in IEEE 754-2008 standard encoding + from the lower 16 bits of integer register `rs1` to the floating-point + register `fd`. The bits are not modified in the transfer, and in particular, + the payloads of non-canonical NaNs are preserved. +definedBy: F +assembly: fd, xs1 +encoding: + match: 111101000000-----000-----1010011 + variables: + - name: rs1 + location: 19-15 + - name: fd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + check_f_ok($encoding); + + Bits<16> hp_value = X[rs1][15:0]; + + f[fd] = nan_box<16, FLEN>(hp_value); + + mark_f_state_dirty(); + + +sail(): | + { + let rs1_val_X = X(rs1); + let rd_val_H = rs1_val_X [15..0]; + F(rd) = nan_box (rd_val_H); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/Zfh/fmv.x.h.yaml b/arch/inst/Zfh/fmv.x.h.yaml index 391b0190a..269579031 100644 --- a/arch/inst/Zfh/fmv.x.h.yaml +++ b/arch/inst/Zfh/fmv.x.h.yaml @@ -1,46 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fmv.x.h: - long_name: Move half-precision value from floating-point to integer register - definedBy: - anyOf: [Zfh, Zfhmin] - assembly: rd, fs1 - description: | - Moves the half-precision value in floating-point register rs1 represented in IEEE 754-2008 - encoding to the lower 16 bits of integer register rd. - - The bits are not modified in the transfer, and in particular, the payloads of non-canonical - NaNs are preserved. - - The highest XLEN-16 bits of the destination register are filled with copies of the - floating-point number's sign bit. - encoding: - match: 111001000000-----000-----1010011 - variables: - - name: fs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - check_f_ok($encoding); - - X[rd] = sext(f[fs1][15:0], 16); - - - - sail(): | - { - let rs1_val_X = X(rs1); - let rd_val_H = rs1_val_X [15..0]; - F(rd) = nan_box (rd_val_H); - RETIRE_SUCCESS - } - - +$schema: "inst_schema.json#" +kind: instruction +name: fmv.x.h +long_name: Move half-precision value from floating-point to integer register +definedBy: + anyOf: [Zfh, Zfhmin] +assembly: rd, fs1 +description: | + Moves the half-precision value in floating-point register rs1 represented in IEEE 754-2008 + encoding to the lower 16 bits of integer register rd. + + The bits are not modified in the transfer, and in particular, the payloads of non-canonical + NaNs are preserved. + + The highest XLEN-16 bits of the destination register are filled with copies of the + floating-point number's sign bit. +encoding: + match: 111001000000-----000-----1010011 + variables: + - name: fs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + check_f_ok($encoding); + + X[rd] = sext(f[fs1][15:0], 16); + + + +sail(): | + { + let rs1_val_X = X(rs1); + let rd_val_H = rs1_val_X [15..0]; + F(rd) = nan_box (rd_val_H); + RETIRE_SUCCESS + } + + diff --git a/arch/inst/Zfh/fsh.yaml b/arch/inst/Zfh/fsh.yaml index 9295c87ea..90d13183d 100644 --- a/arch/inst/Zfh/fsh.yaml +++ b/arch/inst/Zfh/fsh.yaml @@ -1,84 +1,86 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fsh: - long_name: Half-precision floating-point store - description: | - The `fsh` instruction stores a half-precision floating-point value - from register _rd_ to memory at address _rs1_ + _imm_. +$schema: "inst_schema.json#" +kind: instruction +name: fsh +long_name: Half-precision floating-point store +description: | + The `fsh` instruction stores a half-precision floating-point value + from register _rd_ to memory at address _rs1_ + _imm_. - `fsh` does not modify the bits being transferred; in particular, the payloads of non-canonical NaNs are preserved. + `fsh` does not modify the bits being transferred; in particular, the payloads of non-canonical NaNs are preserved. - `fsh` ignores all but the lower 16 bits in _rs2_. + `fsh` ignores all but the lower 16 bits in _rs2_. - `fsh` is only guaranteed to execute atomically if the effective address is naturally aligned. + `fsh` is only guaranteed to execute atomically if the effective address is naturally aligned. - definedBy: - anyOf: [Zfh, Zfhmin] - assembly: fs2, imm(xs1) - encoding: - match: -----------------001-----0100111 - variables: - - name: imm - location: 31-25|11-7 - - name: rs1 - location: 19-15 - - name: fs2 - location: 24-20 - access: - s: always - u: always - vs: always - vu: always - operation(): | - check_f_ok($encoding); +definedBy: + anyOf: [Zfh, Zfhmin] +assembly: fs2, imm(xs1) +encoding: + match: -----------------001-----0100111 + variables: + - name: imm + location: 31-25|11-7 + - name: rs1 + location: 19-15 + - name: fs2 + location: 24-20 +access: + s: always + u: always + vs: always + vu: always +operation(): | + check_f_ok($encoding); - XReg virtual_address = X[rs1] + $signed(imm); + XReg virtual_address = X[rs1] + $signed(imm); - Bits<16> hp_value = f[fs2][15:0]; - - write_memory<16>(virtual_address, hp_value, $encoding); + Bits<16> hp_value = f[fs2][15:0]; + + write_memory<16>(virtual_address, hp_value, $encoding); - sail(): | - { - let offset : xlenbits = sign_extend(imm); - let (aq, rl, con) = (false, false, false); - /* Get the address, X(rs1) + offset. - Some extensions perform additional checks on address validity. */ - match ext_data_get_addr(rs1, offset, Write(Data), width) { - Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, - Ext_DataAddr_OK(vaddr) => - if check_misaligned(vaddr, width) - then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } - else match translateAddr(vaddr, Write(Data)) { - TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - TR_Address(addr, _) => { - let eares : MemoryOpResult(unit) = match width { - BYTE => MemValue () /* bogus placeholder for illegal size */, - HALF => mem_write_ea(addr, 2, aq, rl, false), - WORD => mem_write_ea(addr, 4, aq, rl, false), - DOUBLE => mem_write_ea(addr, 8, aq, rl, false) - }; - match (eares) { - MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, - MemValue(_) => { - let rs2_val = F(rs2); - match (width) { - BYTE => { handle_illegal(); RETIRE_FAIL }, - HALF => process_fstore (vaddr, mem_write_value(addr, 2, rs2_val[15..0], aq, rl, con)), - WORD => process_fstore (vaddr, mem_write_value(addr, 4, rs2_val[31..0], aq, rl, con)), - DOUBLE if sizeof(flen) >= 64 => - process_fstore (vaddr, mem_write_value(addr, 8, rs2_val, aq, rl, con)), - _ => report_invalid_width(__FILE__, __LINE__, width, "floating point store"), - }; - } +sail(): | + { + let offset : xlenbits = sign_extend(imm); + let (aq, rl, con) = (false, false, false); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Write(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Write(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match width { + BYTE => MemValue () /* bogus placeholder for illegal size */, + HALF => mem_write_ea(addr, 2, aq, rl, false), + WORD => mem_write_ea(addr, 4, aq, rl, false), + DOUBLE => mem_write_ea(addr, 8, aq, rl, false) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let rs2_val = F(rs2); + match (width) { + BYTE => { handle_illegal(); RETIRE_FAIL }, + HALF => process_fstore (vaddr, mem_write_value(addr, 2, rs2_val[15..0], aq, rl, con)), + WORD => process_fstore (vaddr, mem_write_value(addr, 4, rs2_val[31..0], aq, rl, con)), + DOUBLE if sizeof(flen) >= 64 => + process_fstore (vaddr, mem_write_value(addr, 8, rs2_val, aq, rl, con)), + _ => report_invalid_width(__FILE__, __LINE__, width, "floating point store"), + }; } } } - } + } } - - + } + + diff --git a/arch/inst/Zicbom/cbo.clean.yaml b/arch/inst/Zicbom/cbo.clean.yaml index 1e60bf9bf..0d933f207 100644 --- a/arch/inst/Zicbom/cbo.clean.yaml +++ b/arch/inst/Zicbom/cbo.clean.yaml @@ -1,70 +1,72 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -cbo.clean: - long_name: Cache Block Clean - description: | - Cleans an entire cache block globally throughout the system. +$schema: "inst_schema.json#" +kind: instruction +name: cbo.clean +long_name: Cache Block Clean +description: | + Cleans an entire cache block globally throughout the system. - Exactly what happens is coherence protocol-dependent, but in general it is expected that after this - operation(): + Exactly what happens is coherence protocol-dependent, but in general it is expected that after this + operation(): - * The cache block will be in the clean (not dirty) state in any coherent cache holding a valid copy of the line. - * The data will be cleaned to a point such that an incoherent load can observe the cleaed data. + * The cache block will be in the clean (not dirty) state in any coherent cache holding a valid copy of the line. + * The data will be cleaned to a point such that an incoherent load can observe the cleaed data. - `cbo.clean` is ordered by `FENCE` instructions but not `FENCE.I` or `SFENCE.VMA`. + `cbo.clean` is ordered by `FENCE` instructions but not `FENCE.I` or `SFENCE.VMA`. - <%- if CACHE_BLOCK_SIZE.bit_length > [PMP_GRANULARITY, PMA_GRANULARITY].min -%> - Both PMP and PMA access control must be the same for all bytes in the block; otherwise, `cbo.clean` has UNSPECIFIED behavior. - <%- end -%> - - Clean operations are treated as stores for page and access permissions. If permission checks fail, - one of the following exceptions will occur: + <%- if CACHE_BLOCK_SIZE.bit_length > [PMP_GRANULARITY, PMA_GRANULARITY].min -%> + Both PMP and PMA access control must be the same for all bytes in the block; otherwise, `cbo.clean` has UNSPECIFIED behavior. + <%- end -%> - <%- if ext?(:H) -%> - * `Store/AMO Guest-Page Fault` if virtual memory translation fails during G-stage translation. - <%- end -%> - * `Store/AMO Page Fault` if virtual memory translation fails <% if ext?(:H) %>when V=0 or during VS-stage translation<% end %> - * `Store/AMO Access Fault` if a PMP or PMA access check fails + Clean operations are treated as stores for page and access permissions. If permission checks fail, + one of the following exceptions will occur: - <%- if CACHE_BLOCK_SIZE.bit_length <= [PMP_GRANULARITY, PMA_GRANULARITY].min -%> - Because cache blocks are naturally aligned and always fit in a single PMP or PMA regions, the PMP - and PMA access checks only need to check a single address in the line. + <%- if ext?(:H) -%> + * `Store/AMO Guest-Page Fault` if virtual memory translation fails during G-stage translation. <%- end -%> + * `Store/AMO Page Fault` if virtual memory translation fails <% if ext?(:H) %>when V=0 or during VS-stage translation<% end %> + * `Store/AMO Access Fault` if a PMP or PMA access check fails + + <%- if CACHE_BLOCK_SIZE.bit_length <= [PMP_GRANULARITY, PMA_GRANULARITY].min -%> + Because cache blocks are naturally aligned and always fit in a single PMP or PMA regions, the PMP + and PMA access checks only need to check a single address in the line. + <%- end -%> - CBO operations never raise a misaligned address fault. - - definedBy: Zicbom - assembly: "TODO" - encoding: - match: 000000000001-----010000000001111 - variables: - - name: rs1 - location: 19-15 - access: - m: always - s: sometimes - u: sometimes - vs: sometimes - vu: sometimes - access_detail: | - Access is controled through `menvcfg.CBZE`, `senvcfg.CBZE`, and `henvcfg.CBZE`. - When access is denied, the instruction either raises an `Illegal Instruction` - or `Virtual Instruction` exception according to the table below. + CBO operations never raise a misaligned address fault. + +definedBy: Zicbom +assembly: "TODO" +encoding: + match: 000000000001-----010000000001111 + variables: + - name: rs1 + location: 19-15 +access: + m: always + s: sometimes + u: sometimes + vs: sometimes + vu: sometimes +access_detail: | + Access is controled through `menvcfg.CBZE`, `senvcfg.CBZE`, and `henvcfg.CBZE`. + When access is denied, the instruction either raises an `Illegal Instruction` + or `Virtual Instruction` exception according to the table below. - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`menvcfg.CBCFE`# .2+h! [.rotate]#`senvcfg.CBCFE`# .2+h! [.rotate]#`henvcfg.CBCFE`# - 4+^.>h! `cbo.clean` Instruction Behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`menvcfg.CBCFE`# .2+h! [.rotate]#`senvcfg.CBCFE`# .2+h! [.rotate]#`henvcfg.CBCFE`# + 4+^.>h! `cbo.clean` Instruction Behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `Illegal Instruction` ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` - ! 1 ! 0 ! 0 ! executes ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` - ! 1 ! 1 ! 0 ! executes ! executes ! `Virtual Instruction` ! `Virtual Instruction` - ! 1 ! 0 ! 1 ! executes ! `Illegal Instruction` ! executes ! `Virtual Instruction` - ! 1 ! 1 ! 1 ! executes ! executes ! executes ! executes - !=== - # operation(): | - # let cache_block_address = X[rs1] & ~(CACHE_BLOCK_SIZE-1); + ! 0 ! - ! - ! `Illegal Instruction` ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` + ! 1 ! 0 ! 0 ! executes ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` + ! 1 ! 1 ! 0 ! executes ! executes ! `Virtual Instruction` ! `Virtual Instruction` + ! 1 ! 0 ! 1 ! executes ! `Illegal Instruction` ! executes ! `Virtual Instruction` + ! 1 ! 1 ! 1 ! executes ! executes ! executes ! executes + !=== +# operation(): | +# let cache_block_address = X[rs1] & ~(CACHE_BLOCK_SIZE-1); - # CACHE_BLOCK_CLEAN(cache_block_address); +# CACHE_BLOCK_CLEAN(cache_block_address); diff --git a/arch/inst/Zicbom/cbo.flush.yaml b/arch/inst/Zicbom/cbo.flush.yaml index 397bc921f..1f9d0e382 100644 --- a/arch/inst/Zicbom/cbo.flush.yaml +++ b/arch/inst/Zicbom/cbo.flush.yaml @@ -1,68 +1,70 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -cbo.flush: - long_name: Cache Block Flush - description: | - Flushes an entire cache block by cleaning it and then invalidating it in all caches. +$schema: "inst_schema.json#" +kind: instruction +name: cbo.flush +long_name: Cache Block Flush +description: | + Flushes an entire cache block by cleaning it and then invalidating it in all caches. - `cbo.flush` is ordered by `FENCE` instructions but not `FENCE.I` or `SFENCE.VMA`. + `cbo.flush` is ordered by `FENCE` instructions but not `FENCE.I` or `SFENCE.VMA`. - <%- if CACHE_BLOCK_SIZE.bit_length > [PMP_GRANULARITY, PMA_GRANULARITY].min -%> - Both PMP and PMA access control must be the same for all bytes in the block; otherwise, `cbo.flush` has UNSPECIFIED behavior. - <%- end -%> - - Flush operations are treated as stores for page and access permissions. If permission checks fail, - one of the following exceptions will occur: + <%- if CACHE_BLOCK_SIZE.bit_length > [PMP_GRANULARITY, PMA_GRANULARITY].min -%> + Both PMP and PMA access control must be the same for all bytes in the block; otherwise, `cbo.flush` has UNSPECIFIED behavior. + <%- end -%> - <%- if ext?(:H) -%> - * `Store/AMO Guest-Page Fault` if virtual memory translation fails during G-stage translation. - <%- end -%> - * `Store/AMO Page Fault` if virtual memory translation fails <% if ext?(:H) %>when V=0 or during VS-stage translation<% end %> - * `Store/AMO Access Fault` if a PMP or PMA access check fails. + Flush operations are treated as stores for page and access permissions. If permission checks fail, + one of the following exceptions will occur: - <%- if CACHE_BLOCK_SIZE.bit_length <= [PMP_GRANULARITY, PMA_GRANULARITY].min -%> - Because cache blocks are naturally aligned and always fit in a single PMP or PMA regions, the PMP - and PMA access checks only need to check a single address in the line. + <%- if ext?(:H) -%> + * `Store/AMO Guest-Page Fault` if virtual memory translation fails during G-stage translation. <%- end -%> - - CBO operations never raise a misaligned address fault. - definedBy: Zicbom - assembly: "TODO" - encoding: - match: 000000000010-----010000000001111 - variables: - - name: rs1 - location: 19-15 - access: - m: always - s: sometimes - u: sometimes - vs: sometimes - vu: sometimes - access_detail: | - Access is controled through `menvcfg.CBZE`, `senvcfg.CBZE`, and `henvcfg.CBZE`. - When access is denied, the instruction either raises an `Illegal Instruction` - or `Virtual Instruction` exception according to the table below. + * `Store/AMO Page Fault` if virtual memory translation fails <% if ext?(:H) %>when V=0 or during VS-stage translation<% end %> + * `Store/AMO Access Fault` if a PMP or PMA access check fails. + + <%- if CACHE_BLOCK_SIZE.bit_length <= [PMP_GRANULARITY, PMA_GRANULARITY].min -%> + Because cache blocks are naturally aligned and always fit in a single PMP or PMA regions, the PMP + and PMA access checks only need to check a single address in the line. + <%- end -%> + + CBO operations never raise a misaligned address fault. +definedBy: Zicbom +assembly: "TODO" +encoding: + match: 000000000010-----010000000001111 + variables: + - name: rs1 + location: 19-15 +access: + m: always + s: sometimes + u: sometimes + vs: sometimes + vu: sometimes +access_detail: | + Access is controled through `menvcfg.CBZE`, `senvcfg.CBZE`, and `henvcfg.CBZE`. + When access is denied, the instruction either raises an `Illegal Instruction` + or `Virtual Instruction` exception according to the table below. - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`menvcfg.CBCFE`# .2+h! [.rotate]#`senvcfg.CBCFE`# .2+h! [.rotate]#`henvcfg.CBCFE`# - 4+^.>h! `cbo.flush` Instruction Behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`menvcfg.CBCFE`# .2+h! [.rotate]#`senvcfg.CBCFE`# .2+h! [.rotate]#`henvcfg.CBCFE`# + 4+^.>h! `cbo.flush` Instruction Behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `Illegal Instruction` ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` - ! 1 ! 0 ! 0 ! executes ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` - ! 1 ! 1 ! 0 ! executes ! executes ! `Virtual Instruction` ! `Virtual Instruction` - ! 1 ! 0 ! 1 ! executes ! `Illegal Instruction` ! executes ! `Virtual Instruction` - ! 1 ! 1 ! 1 ! executes ! executes ! executes ! executes - !=== - # operation(): | - # XReg cache_block_address = X[rs1] & ~(CACHE_BLOCK_SIZE-1); - # Boolean has_fault?; - # ExceptionCode code; + ! 0 ! - ! - ! `Illegal Instruction` ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` + ! 1 ! 0 ! 0 ! executes ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` + ! 1 ! 1 ! 0 ! executes ! executes ! `Virtual Instruction` ! `Virtual Instruction` + ! 1 ! 0 ! 1 ! executes ! `Illegal Instruction` ! executes ! `Virtual Instruction` + ! 1 ! 1 ! 1 ! executes ! executes ! executes ! executes + !=== +# operation(): | +# XReg cache_block_address = X[rs1] & ~(CACHE_BLOCK_SIZE-1); +# Boolean has_fault?; +# ExceptionCode code; - # (has_fault?, code) = zero_cache_line(cache_block_address); - # if (has_fault?) { - # raise(code); - # } +# (has_fault?, code) = zero_cache_line(cache_block_address); +# if (has_fault?) { +# raise(code); +# } diff --git a/arch/inst/Zicbom/cbo.inval.yaml b/arch/inst/Zicbom/cbo.inval.yaml index 73bebfbc0..cfd36a767 100644 --- a/arch/inst/Zicbom/cbo.inval.yaml +++ b/arch/inst/Zicbom/cbo.inval.yaml @@ -1,108 +1,110 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -cbo.inval: - long_name: Cache Block Invalidate - description: | - Either invalidates or flushes (clean + invalidate) a cache block, depending on the current mode and value of - `menvcfg.CBIE`, `senvcfg.CBIE`, and/or `henvcfg.CBIE`. +$schema: "inst_schema.json#" +kind: instruction +name: cbo.inval +long_name: Cache Block Invalidate +description: | + Either invalidates or flushes (clean + invalidate) a cache block, depending on the current mode and value of + `menvcfg.CBIE`, `senvcfg.CBIE`, and/or `henvcfg.CBIE`. - The instruction is an invalidate (without a clean) when: + The instruction is an invalidate (without a clean) when: - * In M-mode - * In (H)S-mode and `menvcfg.CBIE` == 11 - * In U-mode and `menvcfg.CBIE` == 11 and `senvcfg.CBIE` == 11 - * In VS-mode and `menvcfg.CBIE` == 11 and `henvcfg.CBIE` == 11 - * In VU-mode and `menvcfg.CBIE` == 11 and `henvcfg.CBIE` == 11 and `senvcfg.CBIE` == 11 + * In M-mode + * In (H)S-mode and `menvcfg.CBIE` == 11 + * In U-mode and `menvcfg.CBIE` == 11 and `senvcfg.CBIE` == 11 + * In VS-mode and `menvcfg.CBIE` == 11 and `henvcfg.CBIE` == 11 + * In VU-mode and `menvcfg.CBIE` == 11 and `henvcfg.CBIE` == 11 and `senvcfg.CBIE` == 11 - Otherwise, if the instruction does not trap (see Access section), the operation is a flush. - The table below summarizes the options. + Otherwise, if the instruction does not trap (see Access section), the operation is a flush. + The table below summarizes the options. - [%autowidth,cols="1,1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`menvcfg.CBIE`# .2+h! [.rotate]#`senvcfg.CBIE`# .2+h! [.rotate]#`henvcfg.CBIE`# - 5+^.>h! `cbe.inval` Operation - .^h! M-mode .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`menvcfg.CBIE`# .2+h! [.rotate]#`senvcfg.CBIE`# .2+h! [.rotate]#`henvcfg.CBIE`# + 5+^.>h! `cbe.inval` Operation + .^h! M-mode .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 00 ! - ! - ! Invalidate ! `Illegal Instruction` ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` - ! 01 ! 00 ! 00 ! Invalidate ! Flush ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` - ! 01 ! 00 ! 01 ! Invalidate ! Flush ! `Illegal Instruction` ! Flush ! `Virtual Instruction` - ! 01 ! 00 ! 11 ! Invalidate ! Flush ! `Illegal Instruction` ! Flush ! `Virtual Instruction` - ! 01 ! 01 ! 00 ! Invalidate ! Flush ! Flush ! `Virtual Instruction` ! `Virtual Instruction` - ! 01 ! 01 ! 01 ! Invalidate ! Flush ! Flush ! Flush ! Flush - ! 01 ! 01 ! 11 ! Invalidate ! Flush ! Flush ! Flush ! Flush - ! 01 ! 11 ! 00 ! Invalidate ! Flush ! Flush ! `Virtual Instruction` ! `Virtual Instruction` - ! 01 ! 11 ! 01 ! Invalidate ! Flush ! Flush ! Flush ! Flush - ! 01 ! 11 ! 11 ! Invalidate ! Flush ! Flush ! Flush ! Flush - ! 11 ! 00 ! 00 ! Invalidate ! Invalidate ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` - ! 11 ! 00 ! 01 ! Invalidate ! Invalidate ! `Illegal Instruction` ! Flush ! `Virtual Instruction` - ! 11 ! 00 ! 11 ! Invalidate ! Invalidate ! `Illegal Instruction` ! Invalidate ! `Virtual Instruction` - ! 11 ! 01 ! 00 ! Invalidate ! Invalidate ! Flush ! `Virtual Instruction` ! `Virtual Instruction` - ! 11 ! 01 ! 01 ! Invalidate ! Invalidate ! Flush ! Flush ! Flush - ! 11 ! 01 ! 11 ! Invalidate ! Invalidate ! Flush ! Invalidate ! Flush - ! 11 ! 11 ! 00 ! Invalidate ! Invalidate ! Invalidate ! `Virtual Instruction` ! `Virtual Instruction` - ! 11 ! 11 ! 01 ! Invalidate ! Invalidate ! Invalidate ! Flush ! Flush - ! 11 ! 11 ! 11 ! Invalidate ! Invalidate ! Invalidate ! Invalidate ! Invalidate - !=== + ! 00 ! - ! - ! Invalidate ! `Illegal Instruction` ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` + ! 01 ! 00 ! 00 ! Invalidate ! Flush ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` + ! 01 ! 00 ! 01 ! Invalidate ! Flush ! `Illegal Instruction` ! Flush ! `Virtual Instruction` + ! 01 ! 00 ! 11 ! Invalidate ! Flush ! `Illegal Instruction` ! Flush ! `Virtual Instruction` + ! 01 ! 01 ! 00 ! Invalidate ! Flush ! Flush ! `Virtual Instruction` ! `Virtual Instruction` + ! 01 ! 01 ! 01 ! Invalidate ! Flush ! Flush ! Flush ! Flush + ! 01 ! 01 ! 11 ! Invalidate ! Flush ! Flush ! Flush ! Flush + ! 01 ! 11 ! 00 ! Invalidate ! Flush ! Flush ! `Virtual Instruction` ! `Virtual Instruction` + ! 01 ! 11 ! 01 ! Invalidate ! Flush ! Flush ! Flush ! Flush + ! 01 ! 11 ! 11 ! Invalidate ! Flush ! Flush ! Flush ! Flush + ! 11 ! 00 ! 00 ! Invalidate ! Invalidate ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` + ! 11 ! 00 ! 01 ! Invalidate ! Invalidate ! `Illegal Instruction` ! Flush ! `Virtual Instruction` + ! 11 ! 00 ! 11 ! Invalidate ! Invalidate ! `Illegal Instruction` ! Invalidate ! `Virtual Instruction` + ! 11 ! 01 ! 00 ! Invalidate ! Invalidate ! Flush ! `Virtual Instruction` ! `Virtual Instruction` + ! 11 ! 01 ! 01 ! Invalidate ! Invalidate ! Flush ! Flush ! Flush + ! 11 ! 01 ! 11 ! Invalidate ! Invalidate ! Flush ! Invalidate ! Flush + ! 11 ! 11 ! 00 ! Invalidate ! Invalidate ! Invalidate ! `Virtual Instruction` ! `Virtual Instruction` + ! 11 ! 11 ! 01 ! Invalidate ! Invalidate ! Invalidate ! Flush ! Flush + ! 11 ! 11 ! 11 ! Invalidate ! Invalidate ! Invalidate ! Invalidate ! Invalidate + !=== - `cbo.inval` is ordered by `FENCE` instructions but not `FENCE.I` or `SFENCE.VMA`. + `cbo.inval` is ordered by `FENCE` instructions but not `FENCE.I` or `SFENCE.VMA`. - <%- if CACHE_BLOCK_SIZE.bit_length > [PMP_GRANULARITY, PMA_GRANULARITY].min -%> - Both PMP and PMA access control must be the same for all bytes in the block; otherwise, `cbo.zero` has UNSPECIFIED behavior. - <%- end -%> - - Invalidate operations are treated as stores for page and access permissions. If permission checks fail, - one of the following exceptions will occur: + <%- if CACHE_BLOCK_SIZE.bit_length > [PMP_GRANULARITY, PMA_GRANULARITY].min -%> + Both PMP and PMA access control must be the same for all bytes in the block; otherwise, `cbo.zero` has UNSPECIFIED behavior. + <%- end -%> - <%- if ext?(:H) -%> - * `Store/AMO Guest-Page Fault` if virtual memory translation fails during G-stage translation. - <%- end -%> - * `Store/AMO Page Fault` if virtual memory translation fails <% if ext?(:H) %>when V=0 or during VS-stage translation<% end %> - * `Store/AMO Access Fault` if a PMP or PMA access check fails. + Invalidate operations are treated as stores for page and access permissions. If permission checks fail, + one of the following exceptions will occur: - <%- if CACHE_BLOCK_SIZE.bit_length <= [PMP_GRANULARITY, PMA_GRANULARITY].min -%> - Because cache blocks are naturally aligned and always fit in a single PMP or PMA regions, the PMP - and PMA access checks only need to check a single address in the line. + <%- if ext?(:H) -%> + * `Store/AMO Guest-Page Fault` if virtual memory translation fails during G-stage translation. <%- end -%> - - CBO operations never raise a misaligned address fault. - definedBy: Zicbom - assembly: "TODO" - encoding: - match: 000000000000-----010000000001111 - variables: - - name: rs1 - location: 19-15 - access: - m: always - s: sometimes - u: sometimes - vs: sometimes - vu: sometimes - access_detail: | - Access is controled through `menvcfg.CBIE`, `senvcfg.CBIE`, and `henvcfg.CBIE`. - When access is denied, the instruction either raises an `Illegal Instruction` - or `Virtual Instruction` exception according to the table below. + * `Store/AMO Page Fault` if virtual memory translation fails <% if ext?(:H) %>when V=0 or during VS-stage translation<% end %> + * `Store/AMO Access Fault` if a PMP or PMA access check fails. + + <%- if CACHE_BLOCK_SIZE.bit_length <= [PMP_GRANULARITY, PMA_GRANULARITY].min -%> + Because cache blocks are naturally aligned and always fit in a single PMP or PMA regions, the PMP + and PMA access checks only need to check a single address in the line. + <%- end -%> + + CBO operations never raise a misaligned address fault. +definedBy: Zicbom +assembly: "TODO" +encoding: + match: 000000000000-----010000000001111 + variables: + - name: rs1 + location: 19-15 +access: + m: always + s: sometimes + u: sometimes + vs: sometimes + vu: sometimes +access_detail: | + Access is controled through `menvcfg.CBIE`, `senvcfg.CBIE`, and `henvcfg.CBIE`. + When access is denied, the instruction either raises an `Illegal Instruction` + or `Virtual Instruction` exception according to the table below. - [NOTE] - `xenvcfg.CBIE` == 10 is reserved, and cannot be written by software. As such, that pattern is - excluded from the table below. + [NOTE] + `xenvcfg.CBIE` == 10 is reserved, and cannot be written by software. As such, that pattern is + excluded from the table below. - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`menvcfg.CBIE`# .2+h! [.rotate]#`senvcfg.CBIE`# .2+h! [.rotate]#`henvcfg.CBIE`# - 4+^.>h! `cbo.inval` Instruction Behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`menvcfg.CBIE`# .2+h! [.rotate]#`senvcfg.CBIE`# .2+h! [.rotate]#`henvcfg.CBIE`# + 4+^.>h! `cbo.inval` Instruction Behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 00 ! - ! - ! `Illegal Instruction` ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` - ! 01/11 ! 00 ! 00 ! executes ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` - ! 01/11 ! 01/11 ! 00 ! executes ! executes ! `Virtual Instruction` ! `Virtual Instruction` - ! 01/11 ! 00 ! 01/11 ! executes ! `Illegal Instruction` ! executes ! `Virtual Instruction` - ! 01/11 ! 01/11 ! 01/11 ! executes ! executes ! executes ! executes - !=== - # operation(): | - # let cache_block_address = X[RS1] & ~(CACHE_BLOCK_SIZE-1); + ! 00 ! - ! - ! `Illegal Instruction` ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` + ! 01/11 ! 00 ! 00 ! executes ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` + ! 01/11 ! 01/11 ! 00 ! executes ! executes ! `Virtual Instruction` ! `Virtual Instruction` + ! 01/11 ! 00 ! 01/11 ! executes ! `Illegal Instruction` ! executes ! `Virtual Instruction` + ! 01/11 ! 01/11 ! 01/11 ! executes ! executes ! executes ! executes + !=== +# operation(): | +# let cache_block_address = X[RS1] & ~(CACHE_BLOCK_SIZE-1); - # // zeroing operation can occur in any number of independent stores - # for (i=0; i [PMP_GRANULARITY, PMA_GRANULARITY].min -%> - Both PMP and PMA access control must be the same for all bytes in the block; otherwise, `cbo.zero` has UNSPECIFIED behavior. - <%- end -%> - - Clean operations are treated as stores for page and access permissions. If permission checks fail, - one of the following exceptions will occur: + <%- if CACHE_BLOCK_SIZE.bit_length > [PMP_GRANULARITY, PMA_GRANULARITY].min -%> + Both PMP and PMA access control must be the same for all bytes in the block; otherwise, `cbo.zero` has UNSPECIFIED behavior. + <%- end -%> - <%- if ext?(:H) -%> - * `Store/AMO Guest-Page Fault` if virtual memory translation fails during G-stage translation. - <%- end -%> - * `Store/AMO Page Fault` if virtual memory translation fails <% if ext?(:H) %>when V=0 or during VS-stage translation<% end %> - * `Store/AMO Access Fault` if a PMP or PMA access check fails. + Clean operations are treated as stores for page and access permissions. If permission checks fail, + one of the following exceptions will occur: - <%- if CACHE_BLOCK_SIZE.bit_length <= [PMP_GRANULARITY, PMA_GRANULARITY].min -%> - Because cache blocks are naturally aligned and always fit in a single PMP or PMA regions, the PMP - and PMA access checks only need to check a single address in the line. + <%- if ext?(:H) -%> + * `Store/AMO Guest-Page Fault` if virtual memory translation fails during G-stage translation. <%- end -%> - - CBO operations never raise a misaligned address fault. - definedBy: Zicboz - assembly: "TODO" - encoding: - match: 000000000100-----010000000001111 - variables: - - name: rs1 - location: 19-15 - access: - m: always - s: sometimes - u: sometimes - vs: sometimes - vu: sometimes - access_detail: | - Access is controled through `menvcfg.CBZE`, `senvcfg.CBZE`, and `henvcfg.CBZE`. - When access is denied, the instruction either raises an `Illegal Instruction` - or `Virtual Instruction` exception according to the table below. + * `Store/AMO Page Fault` if virtual memory translation fails <% if ext?(:H) %>when V=0 or during VS-stage translation<% end %> + * `Store/AMO Access Fault` if a PMP or PMA access check fails. + + <%- if CACHE_BLOCK_SIZE.bit_length <= [PMP_GRANULARITY, PMA_GRANULARITY].min -%> + Because cache blocks are naturally aligned and always fit in a single PMP or PMA regions, the PMP + and PMA access checks only need to check a single address in the line. + <%- end -%> + + CBO operations never raise a misaligned address fault. +definedBy: Zicboz +assembly: "TODO" +encoding: + match: 000000000100-----010000000001111 + variables: + - name: rs1 + location: 19-15 +access: + m: always + s: sometimes + u: sometimes + vs: sometimes + vu: sometimes +access_detail: | + Access is controled through `menvcfg.CBZE`, `senvcfg.CBZE`, and `henvcfg.CBZE`. + When access is denied, the instruction either raises an `Illegal Instruction` + or `Virtual Instruction` exception according to the table below. - [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] - !=== - .2+h![.rotate]#`menvcfg.CBZE`# .2+h! [.rotate]#`senvcfg.CBZE`# .2+h! [.rotate]#`henvcfg.CBZE`# - 4+^.>h! `cbo.zero` Instruction Behavior - .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode + [%autowidth,cols="1,1,1,1,1,1,1",separator="!"] + !=== + .2+h![.rotate]#`menvcfg.CBZE`# .2+h! [.rotate]#`senvcfg.CBZE`# .2+h! [.rotate]#`henvcfg.CBZE`# + 4+^.>h! `cbo.zero` Instruction Behavior + .^h! S-mode .^h! U-mode .^h! VS-mode .^h! VU-mode - ! 0 ! - ! - ! `Illegal Instruction` ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` - ! 1 ! 0 ! 0 ! executes ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` - ! 1 ! 1 ! 0 ! executes ! executes ! `Virtual Instruction` ! `Virtual Instruction` - ! 1 ! 0 ! 1 ! executes ! `Illegal Instruction` ! executes ! `Virtual Instruction` - ! 1 ! 1 ! 1 ! executes ! executes ! executes ! executes - !=== - operation(): | - if ((mode() == PrivilegeMode::M && CSR[menvcfg].CBZE == 0) || - (mode() == PrivilegeMode::U && CSR[senvcfg].CBZE == 0)) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - else if ((mode() == PrivilegeMode::VS && CSR[henvcfg].CBZE ==0) || - (mode() == PrivilegeMode::VU && (CSR[henvcfg].CBZE | CSR[senvcfg].CBZE) == 0)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } else { - XReg mask = CACHE_BLOCK_SIZE - 1; - XReg cache_block_vaddr = X[rs1] & ~mask; + ! 0 ! - ! - ! `Illegal Instruction` ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` + ! 1 ! 0 ! 0 ! executes ! `Illegal Instruction` ! `Virtual Instruction` ! `Virtual Instruction` + ! 1 ! 1 ! 0 ! executes ! executes ! `Virtual Instruction` ! `Virtual Instruction` + ! 1 ! 0 ! 1 ! executes ! `Illegal Instruction` ! executes ! `Virtual Instruction` + ! 1 ! 1 ! 1 ! executes ! executes ! executes ! executes + !=== +operation(): | + if ((mode() == PrivilegeMode::M && CSR[menvcfg].CBZE == 0) || + (mode() == PrivilegeMode::U && CSR[senvcfg].CBZE == 0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + else if ((mode() == PrivilegeMode::VS && CSR[henvcfg].CBZE ==0) || + (mode() == PrivilegeMode::VU && (CSR[henvcfg].CBZE | CSR[senvcfg].CBZE) == 0)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } else { + XReg mask = CACHE_BLOCK_SIZE - 1; + XReg cache_block_vaddr = X[rs1] & ~mask; - TranslationResult result; - result = translate(cache_block_vaddr, MemoryOperation::Write, effective_ldst_mode(), $encoding); - access_check(result.paddr, CACHE_BLOCK_SIZE*8, cache_block_vaddr, MemoryOperation::Write, ExceptionCode::StoreAmoAccessFault, effective_ldst_mode()); + TranslationResult result; + result = translate(cache_block_vaddr, MemoryOperation::Write, effective_ldst_mode(), $encoding); + access_check(result.paddr, CACHE_BLOCK_SIZE*8, cache_block_vaddr, MemoryOperation::Write, ExceptionCode::StoreAmoAccessFault, effective_ldst_mode()); - cache_block_zero(result.paddr); - } + cache_block_zero(result.paddr); + } diff --git a/arch/inst/Zicfiss/ssamoswap.d.yaml b/arch/inst/Zicfiss/ssamoswap.d.yaml index 0ce26e81a..cda2a4d6e 100644 --- a/arch/inst/Zicfiss/ssamoswap.d.yaml +++ b/arch/inst/Zicfiss/ssamoswap.d.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -ssamoswap.d: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zicfiss - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 01001------------011-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: ssamoswap.d +long_name: No synopsis available. +description: | + No description available. +definedBy: Zicfiss +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 01001------------011-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zicfiss/ssamoswap.w.yaml b/arch/inst/Zicfiss/ssamoswap.w.yaml index 63d2d7cfa..e079f4556 100644 --- a/arch/inst/Zicfiss/ssamoswap.w.yaml +++ b/arch/inst/Zicfiss/ssamoswap.w.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -ssamoswap.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zicfiss - assembly: xd, xs1, xs2, aq, rl - encoding: - match: 01001------------010-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: ssamoswap.w +long_name: No synopsis available. +description: | + No description available. +definedBy: Zicfiss +assembly: xd, xs1, xs2, aq, rl +encoding: + match: 01001------------010-----0101111 + variables: + - name: aq + location: 26-26 + - name: rl + location: 25-25 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zicond/czero.eqz.yaml b/arch/inst/Zicond/czero.eqz.yaml index d00a583b0..f14e7397b 100644 --- a/arch/inst/Zicond/czero.eqz.yaml +++ b/arch/inst/Zicond/czero.eqz.yaml @@ -1,39 +1,40 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -czero.eqz: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zicond - assembly: xd, xs1, xs2 - encoding: - match: 0000111----------101-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: czero.eqz +long_name: No synopsis available. +description: | + No description available. +definedBy: Zicond +assembly: xd, xs1, xs2 +encoding: + match: 0000111----------101-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let value = X(rs1); - let condition = X(rs2); - let result : xlenbits = if (condition != zeros()) then zeros() - else value; - X(rd) = result; - RETIRE_SUCCESS - } - - \ No newline at end of file +sail(): | + { + let value = X(rs1); + let condition = X(rs2); + let result : xlenbits = if (condition != zeros()) then zeros() + else value; + X(rd) = result; + RETIRE_SUCCESS + } + diff --git a/arch/inst/Zicond/czero.nez.yaml b/arch/inst/Zicond/czero.nez.yaml index b296be735..c8dcd203d 100644 --- a/arch/inst/Zicond/czero.nez.yaml +++ b/arch/inst/Zicond/czero.nez.yaml @@ -1,39 +1,40 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -czero.nez: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zicond - assembly: xd, xs1, xs2 - encoding: - match: 0000111----------111-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: czero.nez +long_name: No synopsis available. +description: | + No description available. +definedBy: Zicond +assembly: xd, xs1, xs2 +encoding: + match: 0000111----------111-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + - sail(): | - { - let value = X(rs1); - let condition = X(rs2); - let result : xlenbits = if (condition != zeros()) then zeros() - else value; - X(rd) = result; - RETIRE_SUCCESS - } - - \ No newline at end of file +sail(): | + { + let value = X(rs1); + let condition = X(rs2); + let result : xlenbits = if (condition != zeros()) then zeros() + else value; + X(rd) = result; + RETIRE_SUCCESS + } + diff --git a/arch/inst/Zicsr/csrrs.yaml b/arch/inst/Zicsr/csrrs.yaml index 61a18884d..26e72a75a 100644 --- a/arch/inst/Zicsr/csrrs.yaml +++ b/arch/inst/Zicsr/csrrs.yaml @@ -1,72 +1,74 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -csrrs: - long_name: Atomic Read and Set Bits in CSR - description: | - Atomically read and set bits in a CSR. +$schema: "inst_schema.json#" +kind: instruction +name: csrrs +long_name: Atomic Read and Set Bits in CSR +description: | + Atomically read and set bits in a CSR. - Reads the value of the CSR, zero-extends the value to `XLEN` bits, - and writes it to integer register `rd`. The initial value in integer - register `rs1` is treated as a bit mask that specifies bit positions - to be set in the CSR. Any bit that is high in `rs1` will cause the - corresponding bit to be set in the CSR, if that CSR bit is writable. - Other bits in the CSR are not explicitly written. - definedBy: Zicsr - assembly: xd, xs1, csr - encoding: - match: -----------------000-----0010011 - variables: - - name: csr - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - # TODO: permission checks + Reads the value of the CSR, zero-extends the value to `XLEN` bits, + and writes it to integer register `rd`. The initial value in integer + register `rs1` is treated as a bit mask that specifies bit positions + to be set in the CSR. Any bit that is high in `rs1` will cause the + corresponding bit to be set in the CSR, if that CSR bit is writable. + Other bits in the CSR are not explicitly written. +definedBy: Zicsr +assembly: xd, xs1, csr +encoding: + match: -----------------000-----0010011 + variables: + - name: csr + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + # TODO: permission checks - XReg initial_csr_value = CSR[csr].sw_read(); - XReg mask = X[rs1]; + XReg initial_csr_value = CSR[csr].sw_read(); + XReg mask = X[rs1]; - # set bits using the mask - # performing any WARL transformations first - CSR[csr].sw_write(initial_csr_value | mask); + # set bits using the mask + # performing any WARL transformations first + CSR[csr].sw_write(initial_csr_value | mask); - X[rd] = initial_csr_value; + X[rd] = initial_csr_value; - sail(): | - { - let rs1_val : xlenbits = if is_imm then zero_extend(rs1) else X(rs1); - let isWrite : bool = match op { - CSRRW => true, - _ => if is_imm then unsigned(rs1_val) != 0 else unsigned(rs1) != 0 - }; - if not(check_CSR(csr, cur_privilege, isWrite)) - then { handle_illegal(); RETIRE_FAIL } - else if not(ext_check_CSR(csr, cur_privilege, isWrite)) - then { ext_check_CSR_fail(); RETIRE_FAIL } - else { - let csr_val = readCSR(csr); /* could have side-effects, so technically shouldn't perform for CSRW[I] with rd == 0 */ - if isWrite then { - let new_val : xlenbits = match op { - CSRRW => rs1_val, - CSRRS => csr_val | rs1_val, - CSRRC => csr_val & ~(rs1_val) - }; - writeCSR(csr, new_val) +sail(): | + { + let rs1_val : xlenbits = if is_imm then zero_extend(rs1) else X(rs1); + let isWrite : bool = match op { + CSRRW => true, + _ => if is_imm then unsigned(rs1_val) != 0 else unsigned(rs1) != 0 + }; + if not(check_CSR(csr, cur_privilege, isWrite)) + then { handle_illegal(); RETIRE_FAIL } + else if not(ext_check_CSR(csr, cur_privilege, isWrite)) + then { ext_check_CSR_fail(); RETIRE_FAIL } + else { + let csr_val = readCSR(csr); /* could have side-effects, so technically shouldn't perform for CSRW[I] with rd == 0 */ + if isWrite then { + let new_val : xlenbits = match op { + CSRRW => rs1_val, + CSRRS => csr_val | rs1_val, + CSRRC => csr_val & ~(rs1_val) }; - X(rd) = csr_val; - RETIRE_SUCCESS - } + writeCSR(csr, new_val) + }; + X(rd) = csr_val; + RETIRE_SUCCESS } - - + } + + diff --git a/arch/inst/Zicsr/csrrw.yaml b/arch/inst/Zicsr/csrrw.yaml index 28188e4af..0e4ba92c7 100644 --- a/arch/inst/Zicsr/csrrw.yaml +++ b/arch/inst/Zicsr/csrrw.yaml @@ -1,68 +1,70 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -csrrw: - long_name: Atomic Read/Write CSR - description: | - Atomically swap values in the CSRs and integer registers. +$schema: "inst_schema.json#" +kind: instruction +name: csrrw +long_name: Atomic Read/Write CSR +description: | + Atomically swap values in the CSRs and integer registers. - Read the old value of the CSR, zero-extends the value to `XLEN` bits, - and then write it to integer register rd. - The initial value in rs1 is written to the CSR. - If `rd=x0`, then the instruction shall not read the CSR and shall not - cause any of the side effects that might occur on a CSR read. - definedBy: Zicsr - assembly: xd, xs1, csr - encoding: - match: -----------------001-----1110011 - variables: - - name: csr - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (rd != 0) { - X[rd] = CSR[csr].sw_read(); - } + Read the old value of the CSR, zero-extends the value to `XLEN` bits, + and then write it to integer register rd. + The initial value in rs1 is written to the CSR. + If `rd=x0`, then the instruction shall not read the CSR and shall not + cause any of the side effects that might occur on a CSR read. +definedBy: Zicsr +assembly: xd, xs1, csr +encoding: + match: -----------------001-----1110011 + variables: + - name: csr + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (rd != 0) { + X[rd] = CSR[csr].sw_read(); + } - # writes the value in X[rs1] to the CSR, - # performing any WARL transformations first - CSR[csr].sw_write(X[rs1]); + # writes the value in X[rs1] to the CSR, + # performing any WARL transformations first + CSR[csr].sw_write(X[rs1]); - sail(): | - { - let rs1_val : xlenbits = if is_imm then zero_extend(rs1) else X(rs1); - let isWrite : bool = match op { - CSRRW => true, - _ => if is_imm then unsigned(rs1_val) != 0 else unsigned(rs1) != 0 - }; - if not(check_CSR(csr, cur_privilege, isWrite)) - then { handle_illegal(); RETIRE_FAIL } - else if not(ext_check_CSR(csr, cur_privilege, isWrite)) - then { ext_check_CSR_fail(); RETIRE_FAIL } - else { - let csr_val = readCSR(csr); /* could have side-effects, so technically shouldn't perform for CSRW[I] with rd == 0 */ - if isWrite then { - let new_val : xlenbits = match op { - CSRRW => rs1_val, - CSRRS => csr_val | rs1_val, - CSRRC => csr_val & ~(rs1_val) - }; - writeCSR(csr, new_val) +sail(): | + { + let rs1_val : xlenbits = if is_imm then zero_extend(rs1) else X(rs1); + let isWrite : bool = match op { + CSRRW => true, + _ => if is_imm then unsigned(rs1_val) != 0 else unsigned(rs1) != 0 + }; + if not(check_CSR(csr, cur_privilege, isWrite)) + then { handle_illegal(); RETIRE_FAIL } + else if not(ext_check_CSR(csr, cur_privilege, isWrite)) + then { ext_check_CSR_fail(); RETIRE_FAIL } + else { + let csr_val = readCSR(csr); /* could have side-effects, so technically shouldn't perform for CSRW[I] with rd == 0 */ + if isWrite then { + let new_val : xlenbits = match op { + CSRRW => rs1_val, + CSRRS => csr_val | rs1_val, + CSRRC => csr_val & ~(rs1_val) }; - X(rd) = csr_val; - RETIRE_SUCCESS - } + writeCSR(csr, new_val) + }; + X(rd) = csr_val; + RETIRE_SUCCESS } - - + } + + diff --git a/arch/inst/Zicsr/csrrwi.yaml b/arch/inst/Zicsr/csrrwi.yaml index 72ca7a7cb..7a304af4f 100644 --- a/arch/inst/Zicsr/csrrwi.yaml +++ b/arch/inst/Zicsr/csrrwi.yaml @@ -1,68 +1,70 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -csrrwi: - long_name: Atomic Read/Write CSR Immediate - description: | - Atomically write CSR using a 5-bit immediate, and load the previous value into 'rd'. +$schema: "inst_schema.json#" +kind: instruction +name: csrrwi +long_name: Atomic Read/Write CSR Immediate +description: | + Atomically write CSR using a 5-bit immediate, and load the previous value into 'rd'. - Read the old value of the CSR, zero-extends the value to `XLEN` bits, - and then write it to integer register rd. - The 5-bit uimm field is zero-extended and written to the CSR. - If `rd=x0`, then the instruction shall not read the CSR and shall not - cause any of the side effects that might occur on a CSR read. - definedBy: Zicsr - assembly: xd, zimm, csr - encoding: - match: -----------------101-----1110011 - variables: - - name: csr - location: 31-20 - - name: imm - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - if (rd != 0) { - X[rd] = CSR[csr].sw_read(); - } + Read the old value of the CSR, zero-extends the value to `XLEN` bits, + and then write it to integer register rd. + The 5-bit uimm field is zero-extended and written to the CSR. + If `rd=x0`, then the instruction shall not read the CSR and shall not + cause any of the side effects that might occur on a CSR read. +definedBy: Zicsr +assembly: xd, zimm, csr +encoding: + match: -----------------101-----1110011 + variables: + - name: csr + location: 31-20 + - name: imm + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (rd != 0) { + X[rd] = CSR[csr].sw_read(); + } - # writes the zero-extended immediate to the CSR, - # performing any WARL transformations first - CSR[csr].sw_write({{XLEN-5{1'b0}}, imm}); + # writes the zero-extended immediate to the CSR, + # performing any WARL transformations first + CSR[csr].sw_write({{XLEN-5{1'b0}}, imm}); - sail(): | - { - let rs1_val : xlenbits = if is_imm then zero_extend(rs1) else X(rs1); - let isWrite : bool = match op { - CSRRW => true, - _ => if is_imm then unsigned(rs1_val) != 0 else unsigned(rs1) != 0 - }; - if not(check_CSR(csr, cur_privilege, isWrite)) - then { handle_illegal(); RETIRE_FAIL } - else if not(ext_check_CSR(csr, cur_privilege, isWrite)) - then { ext_check_CSR_fail(); RETIRE_FAIL } - else { - let csr_val = readCSR(csr); /* could have side-effects, so technically shouldn't perform for CSRW[I] with rd == 0 */ - if isWrite then { - let new_val : xlenbits = match op { - CSRRW => rs1_val, - CSRRS => csr_val | rs1_val, - CSRRC => csr_val & ~(rs1_val) - }; - writeCSR(csr, new_val) +sail(): | + { + let rs1_val : xlenbits = if is_imm then zero_extend(rs1) else X(rs1); + let isWrite : bool = match op { + CSRRW => true, + _ => if is_imm then unsigned(rs1_val) != 0 else unsigned(rs1) != 0 + }; + if not(check_CSR(csr, cur_privilege, isWrite)) + then { handle_illegal(); RETIRE_FAIL } + else if not(ext_check_CSR(csr, cur_privilege, isWrite)) + then { ext_check_CSR_fail(); RETIRE_FAIL } + else { + let csr_val = readCSR(csr); /* could have side-effects, so technically shouldn't perform for CSRW[I] with rd == 0 */ + if isWrite then { + let new_val : xlenbits = match op { + CSRRW => rs1_val, + CSRRS => csr_val | rs1_val, + CSRRC => csr_val & ~(rs1_val) }; - X(rd) = csr_val; - RETIRE_SUCCESS - } + writeCSR(csr, new_val) + }; + X(rd) = csr_val; + RETIRE_SUCCESS } - - + } + + diff --git a/arch/inst/Zifencei/fence.i.yaml b/arch/inst/Zifencei/fence.i.yaml index b968226a6..f829bb961 100644 --- a/arch/inst/Zifencei/fence.i.yaml +++ b/arch/inst/Zifencei/fence.i.yaml @@ -1,57 +1,59 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -fence.i: - long_name: Instruction fence - description: | - The FENCE.I instruction is used to synchronize the instruction and data - streams. RISC-V does not guarantee that stores to instruction memory - will be made visible to instruction fetches on a RISC-V hart until that - hart executes a FENCE.I instruction. A FENCE.I instruction ensures that - a subsequent instruction fetch on a RISC-V hart will see any previous - data stores already visible to the same RISC-V hart. FENCE.I does _not_ - ensure that other RISC-V harts' instruction fetches will observe the - local hart's stores in a multiprocessor system. To make a store to - instruction memory visible to all RISC-V harts, the writing hart also - has to execute a data FENCE before requesting that all remote RISC-V - harts execute a FENCE.I. - - The unused fields in the FENCE.I instruction, _imm[11:0]_, _rs1_, and - _rd_, are reserved for finer-grain fences in future extensions. For - forward compatibility, base implementations shall ignore these fields, - and standard software shall zero these fields. - (((FENCE.I, finer-grained))) - (((FENCE.I, forward compatibility))) - - [NOTE] - ==== - Because FENCE.I only orders stores with a hart's own instruction - fetches, application code should only rely upon FENCE.I if the - application thread will not be migrated to a different hart. The EEI can - provide mechanisms for efficient multiprocessor instruction-stream - synchronization. - ==== - definedBy: Zifencei - assembly: "" - encoding: - match: -----------------001-----0001111 - variables: - - name: imm - location: 31-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - operation(): | - ifence(); - - sail(): | - { /* __barrier(Barrier_RISCV_i); */ RETIRE_SUCCESS } - +$schema: "inst_schema.json#" +kind: instruction +name: fence.i +long_name: Instruction fence +description: | + The FENCE.I instruction is used to synchronize the instruction and data + streams. RISC-V does not guarantee that stores to instruction memory + will be made visible to instruction fetches on a RISC-V hart until that + hart executes a FENCE.I instruction. A FENCE.I instruction ensures that + a subsequent instruction fetch on a RISC-V hart will see any previous + data stores already visible to the same RISC-V hart. FENCE.I does _not_ + ensure that other RISC-V harts' instruction fetches will observe the + local hart's stores in a multiprocessor system. To make a store to + instruction memory visible to all RISC-V harts, the writing hart also + has to execute a data FENCE before requesting that all remote RISC-V + harts execute a FENCE.I. + + The unused fields in the FENCE.I instruction, _imm[11:0]_, _rs1_, and + _rd_, are reserved for finer-grain fences in future extensions. For + forward compatibility, base implementations shall ignore these fields, + and standard software shall zero these fields. + (((FENCE.I, finer-grained))) + (((FENCE.I, forward compatibility))) + + [NOTE] + ==== + Because FENCE.I only orders stores with a hart's own instruction + fetches, application code should only rely upon FENCE.I if the + application thread will not be migrated to a different hart. The EEI can + provide mechanisms for efficient multiprocessor instruction-stream + synchronization. + ==== +definedBy: Zifencei +assembly: "" +encoding: + match: -----------------001-----0001111 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + ifence(); + +sail(): | + { /* __barrier(Barrier_RISCV_i); */ RETIRE_SUCCESS } + diff --git a/arch/inst/Zimop/mop.r.n.yaml b/arch/inst/Zimop/mop.r.n.yaml index 69acaabf2..bc90d9beb 100644 --- a/arch/inst/Zimop/mop.r.n.yaml +++ b/arch/inst/Zimop/mop.r.n.yaml @@ -1,94 +1,96 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -mop.r.n: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zimop - assembly: mop_r_t_30, mop_r_t_27_26, mop_r_t_21_20, xd, xs1 - encoding: - match: 1-00--0111-------100-----1110011 - variables: - - name: mop_r_t_30 - location: 30-30 - - name: mop_r_t_27_26 - location: 27-26 - - name: mop_r_t_21_20 - location: 21-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - pseudoinstructions: - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x0) - to: mop.r.0 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x0) - to: mop.r.1 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x0) - to: mop.r.2 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x0) - to: mop.r.3 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x1) - to: mop.r.4 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x1) - to: mop.r.5 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x1) - to: mop.r.6 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x1) - to: mop.r.7 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x2) - to: mop.r.8 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x2) - to: mop.r.9 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x2) - to: mop.r.10 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x2) - to: mop.r.11 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x3) - to: mop.r.12 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x3) - to: mop.r.13 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x3) - to: mop.r.14 - - when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x3) - to: mop.r.15 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x0) - to: mop.r.16 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x0) - to: mop.r.17 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x0) - to: mop.r.18 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x0) - to: mop.r.19 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x1) - to: mop.r.20 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x1) - to: mop.r.21 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x1) - to: mop.r.22 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x1) - to: mop.r.23 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x2) - to: mop.r.24 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x2) - to: mop.r.25 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x2) - to: mop.r.26 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x2) - to: mop.r.27 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x3) - to: mop.r.28 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x3) - to: mop.r.29 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x3) - to: mop.r.30 - - when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x3) - to: mop.r.31 - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: mop.r.n +long_name: No synopsis available. +description: | + No description available. +definedBy: Zimop +assembly: mop_r_t_30, mop_r_t_27_26, mop_r_t_21_20, xd, xs1 +encoding: + match: 1-00--0111-------100-----1110011 + variables: + - name: mop_r_t_30 + location: 30-30 + - name: mop_r_t_27_26 + location: 27-26 + - name: mop_r_t_21_20 + location: 21-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +pseudoinstructions: +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x0) + to: mop.r.0 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x0) + to: mop.r.1 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x0) + to: mop.r.2 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x0) + to: mop.r.3 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x1) + to: mop.r.4 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x1) + to: mop.r.5 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x1) + to: mop.r.6 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x1) + to: mop.r.7 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x2) + to: mop.r.8 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x2) + to: mop.r.9 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x2) + to: mop.r.10 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x2) + to: mop.r.11 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x3) + to: mop.r.12 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x3) + to: mop.r.13 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x3) + to: mop.r.14 +- when: (mop_r_t_30 == 0x0) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x3) + to: mop.r.15 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x0) + to: mop.r.16 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x0) + to: mop.r.17 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x0) + to: mop.r.18 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x0) + to: mop.r.19 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x1) + to: mop.r.20 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x1) + to: mop.r.21 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x1) + to: mop.r.22 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x1) + to: mop.r.23 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x2) + to: mop.r.24 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x2) + to: mop.r.25 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x2) + to: mop.r.26 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x2) + to: mop.r.27 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x0) && (mop_r_t_27_26 == 0x3) + to: mop.r.28 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x1) && (mop_r_t_27_26 == 0x3) + to: mop.r.29 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x2) && (mop_r_t_27_26 == 0x3) + to: mop.r.30 +- when: (mop_r_t_30 == 0x1) && (mop_r_t_21_20 == 0x3) && (mop_r_t_27_26 == 0x3) + to: mop.r.31 +operation(): | + diff --git a/arch/inst/Zimop/mop.rr.n.yaml b/arch/inst/Zimop/mop.rr.n.yaml index b0a35eb8c..e8de57ec7 100644 --- a/arch/inst/Zimop/mop.rr.n.yaml +++ b/arch/inst/Zimop/mop.rr.n.yaml @@ -1,46 +1,48 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -mop.rr.n: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zimop - assembly: mop_rr_t_30, mop_rr_t_27_26, xd, xs1, xs2 - encoding: - match: 1-00--1----------100-----1110011 - variables: - - name: mop_rr_t_30 - location: 30-30 - - name: mop_rr_t_27_26 - location: 27-26 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - pseudoinstructions: - - when: (mop_rr_t_30 == 0x0) && (mop_rr_t_27_26 == 0x0) - to: mop.rr.0 - - when: (mop_rr_t_30 == 0x0) && (mop_rr_t_27_26 == 0x1) - to: mop.rr.1 - - when: (mop_rr_t_30 == 0x0) && (mop_rr_t_27_26 == 0x2) - to: mop.rr.2 - - when: (mop_rr_t_30 == 0x0) && (mop_rr_t_27_26 == 0x3) - to: mop.rr.3 - - when: (mop_rr_t_30 == 0x1) && (mop_rr_t_27_26 == 0x0) - to: mop.rr.4 - - when: (mop_rr_t_30 == 0x1) && (mop_rr_t_27_26 == 0x1) - to: mop.rr.5 - - when: (mop_rr_t_30 == 0x1) && (mop_rr_t_27_26 == 0x2) - to: mop.rr.6 - - when: (mop_rr_t_30 == 0x1) && (mop_rr_t_27_26 == 0x3) - to: mop.rr.7 - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: mop.rr.n +long_name: No synopsis available. +description: | + No description available. +definedBy: Zimop +assembly: mop_rr_t_30, mop_rr_t_27_26, xd, xs1, xs2 +encoding: + match: 1-00--1----------100-----1110011 + variables: + - name: mop_rr_t_30 + location: 30-30 + - name: mop_rr_t_27_26 + location: 27-26 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +pseudoinstructions: +- when: (mop_rr_t_30 == 0x0) && (mop_rr_t_27_26 == 0x0) + to: mop.rr.0 +- when: (mop_rr_t_30 == 0x0) && (mop_rr_t_27_26 == 0x1) + to: mop.rr.1 +- when: (mop_rr_t_30 == 0x0) && (mop_rr_t_27_26 == 0x2) + to: mop.rr.2 +- when: (mop_rr_t_30 == 0x0) && (mop_rr_t_27_26 == 0x3) + to: mop.rr.3 +- when: (mop_rr_t_30 == 0x1) && (mop_rr_t_27_26 == 0x0) + to: mop.rr.4 +- when: (mop_rr_t_30 == 0x1) && (mop_rr_t_27_26 == 0x1) + to: mop.rr.5 +- when: (mop_rr_t_30 == 0x1) && (mop_rr_t_27_26 == 0x2) + to: mop.rr.6 +- when: (mop_rr_t_30 == 0x1) && (mop_rr_t_27_26 == 0x3) + to: mop.rr.7 +operation(): | + diff --git a/arch/inst/Zk/aes32dsi.yaml b/arch/inst/Zk/aes32dsi.yaml index ed2481d96..4c6a4b8fe 100644 --- a/arch/inst/Zk/aes32dsi.yaml +++ b/arch/inst/Zk/aes32dsi.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -aes32dsi: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknd] - base: 32 - assembly: xd, xs1, xs2, bs - encoding: - match: --10101----------000-----0110011 - variables: - - name: bs - location: 31-30 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: aes32dsi +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknd] +base: 32 +assembly: xd, xs1, xs2, bs +encoding: + match: --10101----------000-----0110011 + variables: + - name: bs + location: 31-30 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/aes32dsmi.yaml b/arch/inst/Zk/aes32dsmi.yaml index 5af88bf73..d94fef7d4 100644 --- a/arch/inst/Zk/aes32dsmi.yaml +++ b/arch/inst/Zk/aes32dsmi.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -aes32dsmi: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknd] - base: 32 - assembly: xd, xs1, xs2, bs - encoding: - match: --10111----------000-----0110011 - variables: - - name: bs - location: 31-30 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: aes32dsmi +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknd] +base: 32 +assembly: xd, xs1, xs2, bs +encoding: + match: --10111----------000-----0110011 + variables: + - name: bs + location: 31-30 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/aes32esi.yaml b/arch/inst/Zk/aes32esi.yaml index 0e1e69242..378aa0670 100644 --- a/arch/inst/Zk/aes32esi.yaml +++ b/arch/inst/Zk/aes32esi.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -aes32esi: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zkne] - base: 32 - assembly: xd, xs1, xs2, bs - encoding: - match: --10001----------000-----0110011 - variables: - - name: bs - location: 31-30 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: aes32esi +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zkne] +base: 32 +assembly: xd, xs1, xs2, bs +encoding: + match: --10001----------000-----0110011 + variables: + - name: bs + location: 31-30 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/aes32esmi.yaml b/arch/inst/Zk/aes32esmi.yaml index 417b832f9..879bf4114 100644 --- a/arch/inst/Zk/aes32esmi.yaml +++ b/arch/inst/Zk/aes32esmi.yaml @@ -1,29 +1,31 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -aes32esmi: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zkne] - base: 32 - assembly: xd, xs1, xs2, bs - encoding: - match: --10011----------000-----0110011 - variables: - - name: bs - location: 31-30 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: aes32esmi +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zkne] +base: 32 +assembly: xd, xs1, xs2, bs +encoding: + match: --10011----------000-----0110011 + variables: + - name: bs + location: 31-30 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/aes64ds.yaml b/arch/inst/Zk/aes64ds.yaml index a6ce42312..07ebdac8c 100644 --- a/arch/inst/Zk/aes64ds.yaml +++ b/arch/inst/Zk/aes64ds.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -aes64ds: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknd] - base: 64 - assembly: xd, xs1, xs2 - encoding: - match: 0011101----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: aes64ds +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknd] +base: 64 +assembly: xd, xs1, xs2 +encoding: + match: 0011101----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/aes64dsm.yaml b/arch/inst/Zk/aes64dsm.yaml index 19b28b71a..b4f744fd0 100644 --- a/arch/inst/Zk/aes64dsm.yaml +++ b/arch/inst/Zk/aes64dsm.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -aes64dsm: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknd] - base: 64 - assembly: xd, xs1, xs2 - encoding: - match: 0011111----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: aes64dsm +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknd] +base: 64 +assembly: xd, xs1, xs2 +encoding: + match: 0011111----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/aes64es.yaml b/arch/inst/Zk/aes64es.yaml index 146578b20..4e50e4062 100644 --- a/arch/inst/Zk/aes64es.yaml +++ b/arch/inst/Zk/aes64es.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -aes64es: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zkne] - base: 64 - assembly: xd, xs1, xs2 - encoding: - match: 0011001----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: aes64es +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zkne] +base: 64 +assembly: xd, xs1, xs2 +encoding: + match: 0011001----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/aes64esm.yaml b/arch/inst/Zk/aes64esm.yaml index c1393e491..af29db499 100644 --- a/arch/inst/Zk/aes64esm.yaml +++ b/arch/inst/Zk/aes64esm.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -aes64esm: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zkne] - base: 64 - assembly: xd, xs1, xs2 - encoding: - match: 0011011----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: aes64esm +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zkne] +base: 64 +assembly: xd, xs1, xs2 +encoding: + match: 0011011----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/aes64im.yaml b/arch/inst/Zk/aes64im.yaml index b9966f8c6..d0ab1847c 100644 --- a/arch/inst/Zk/aes64im.yaml +++ b/arch/inst/Zk/aes64im.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -aes64im: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknd] - base: 64 - assembly: xd, xs1 - encoding: - match: 001100000000-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: aes64im +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknd] +base: 64 +assembly: xd, xs1 +encoding: + match: 001100000000-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/aes64ks1i.yaml b/arch/inst/Zk/aes64ks1i.yaml index d5b51f52c..30b9e1cfc 100644 --- a/arch/inst/Zk/aes64ks1i.yaml +++ b/arch/inst/Zk/aes64ks1i.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -aes64ks1i: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknd, Zkne] - base: 64 - assembly: xd, xs1, rnum - encoding: - match: 00110001---------001-----0010011 - variables: - - name: rnum - location: 23-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: aes64ks1i +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknd, Zkne] +base: 64 +assembly: xd, xs1, rnum +encoding: + match: 00110001---------001-----0010011 + variables: + - name: rnum + location: 23-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/aes64ks2.yaml b/arch/inst/Zk/aes64ks2.yaml index 117f1158c..a332f844c 100644 --- a/arch/inst/Zk/aes64ks2.yaml +++ b/arch/inst/Zk/aes64ks2.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -aes64ks2: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknd, Zkne] - base: 64 - assembly: xd, xs1, xs2 - encoding: - match: 0111111----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: aes64ks2 +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknd, Zkne] +base: 64 +assembly: xd, xs1, xs2 +encoding: + match: 0111111----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/pack.yaml b/arch/inst/Zk/pack.yaml index c19462762..49e915a75 100644 --- a/arch/inst/Zk/pack.yaml +++ b/arch/inst/Zk/pack.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -pack: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zbkb, Zk, Zkn, Zks] - assembly: xd, xs1, xs2 - encoding: - match: 0000100----------100-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: pack +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zbkb, Zk, Zkn, Zks] +assembly: xd, xs1, xs2 +encoding: + match: 0000100----------100-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/packh.yaml b/arch/inst/Zk/packh.yaml index 2561af41b..3e8b5f79e 100644 --- a/arch/inst/Zk/packh.yaml +++ b/arch/inst/Zk/packh.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -packh: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zbkb, Zk, Zkn, Zks] - assembly: xd, xs1, xs2 - encoding: - match: 0000100----------111-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: packh +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zbkb, Zk, Zkn, Zks] +assembly: xd, xs1, xs2 +encoding: + match: 0000100----------111-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/packw.yaml b/arch/inst/Zk/packw.yaml index 71871de5b..12b2f0eb6 100644 --- a/arch/inst/Zk/packw.yaml +++ b/arch/inst/Zk/packw.yaml @@ -1,30 +1,32 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -packw: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zbkb, Zk, Zkn, Zks] - base: 64 - assembly: xd, xs1, xs2 - encoding: - match: 0000100----------100-----0111011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - pseudoinstructions: - - when: (rs2 == 0x0) - to: zext.h - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: packw +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zbkb, Zk, Zkn, Zks] +base: 64 +assembly: xd, xs1, xs2 +encoding: + match: 0000100----------100-----0111011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +pseudoinstructions: +- when: (rs2 == 0x0) + to: zext.h +operation(): | + diff --git a/arch/inst/Zk/sha256sig0.yaml b/arch/inst/Zk/sha256sig0.yaml index ad1f81b39..8a6ac1cb6 100644 --- a/arch/inst/Zk/sha256sig0.yaml +++ b/arch/inst/Zk/sha256sig0.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha256sig0: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - assembly: xd, xs1 - encoding: - match: 000100000010-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha256sig0 +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +assembly: xd, xs1 +encoding: + match: 000100000010-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/sha256sig1.yaml b/arch/inst/Zk/sha256sig1.yaml index 5b979578f..377612933 100644 --- a/arch/inst/Zk/sha256sig1.yaml +++ b/arch/inst/Zk/sha256sig1.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha256sig1: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - assembly: xd, xs1 - encoding: - match: 000100000011-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha256sig1 +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +assembly: xd, xs1 +encoding: + match: 000100000011-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/sha256sum0.yaml b/arch/inst/Zk/sha256sum0.yaml index 6cf26bda2..eda4a5c35 100644 --- a/arch/inst/Zk/sha256sum0.yaml +++ b/arch/inst/Zk/sha256sum0.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha256sum0: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - assembly: xd, xs1 - encoding: - match: 000100000000-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha256sum0 +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +assembly: xd, xs1 +encoding: + match: 000100000000-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/sha256sum1.yaml b/arch/inst/Zk/sha256sum1.yaml index 98bc7c420..fa4876685 100644 --- a/arch/inst/Zk/sha256sum1.yaml +++ b/arch/inst/Zk/sha256sum1.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha256sum1: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - assembly: xd, xs1 - encoding: - match: 000100000001-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha256sum1 +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +assembly: xd, xs1 +encoding: + match: 000100000001-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/sha512sig0.yaml b/arch/inst/Zk/sha512sig0.yaml index 7e36fb5d8..f7d4f909a 100644 --- a/arch/inst/Zk/sha512sig0.yaml +++ b/arch/inst/Zk/sha512sig0.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha512sig0: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - base: 64 - assembly: xd, xs1 - encoding: - match: 000100000110-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha512sig0 +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +base: 64 +assembly: xd, xs1 +encoding: + match: 000100000110-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/sha512sig0h.yaml b/arch/inst/Zk/sha512sig0h.yaml index 7aa005691..872046027 100644 --- a/arch/inst/Zk/sha512sig0h.yaml +++ b/arch/inst/Zk/sha512sig0h.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha512sig0h: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - base: 32 - assembly: xd, xs1, xs2 - encoding: - match: 0101110----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha512sig0h +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +base: 32 +assembly: xd, xs1, xs2 +encoding: + match: 0101110----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/sha512sig0l.yaml b/arch/inst/Zk/sha512sig0l.yaml index e233b6826..df86a0356 100644 --- a/arch/inst/Zk/sha512sig0l.yaml +++ b/arch/inst/Zk/sha512sig0l.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha512sig0l: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - base: 32 - assembly: xd, xs1, xs2 - encoding: - match: 0101010----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha512sig0l +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +base: 32 +assembly: xd, xs1, xs2 +encoding: + match: 0101010----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/sha512sig1.yaml b/arch/inst/Zk/sha512sig1.yaml index 1b4558038..e75977bb4 100644 --- a/arch/inst/Zk/sha512sig1.yaml +++ b/arch/inst/Zk/sha512sig1.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha512sig1: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - base: 64 - assembly: xd, xs1 - encoding: - match: 000100000111-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha512sig1 +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +base: 64 +assembly: xd, xs1 +encoding: + match: 000100000111-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/sha512sig1h.yaml b/arch/inst/Zk/sha512sig1h.yaml index 52c3e5881..2ae02b4e3 100644 --- a/arch/inst/Zk/sha512sig1h.yaml +++ b/arch/inst/Zk/sha512sig1h.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha512sig1h: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - base: 32 - assembly: xd, xs1, xs2 - encoding: - match: 0101111----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha512sig1h +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +base: 32 +assembly: xd, xs1, xs2 +encoding: + match: 0101111----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/sha512sig1l.yaml b/arch/inst/Zk/sha512sig1l.yaml index 8e281fadb..c1f26069d 100644 --- a/arch/inst/Zk/sha512sig1l.yaml +++ b/arch/inst/Zk/sha512sig1l.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha512sig1l: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - base: 32 - assembly: xd, xs1, xs2 - encoding: - match: 0101011----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha512sig1l +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +base: 32 +assembly: xd, xs1, xs2 +encoding: + match: 0101011----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/sha512sum0.yaml b/arch/inst/Zk/sha512sum0.yaml index 0eff8a989..3d8c409c6 100644 --- a/arch/inst/Zk/sha512sum0.yaml +++ b/arch/inst/Zk/sha512sum0.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha512sum0: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - base: 64 - assembly: xd, xs1 - encoding: - match: 000100000100-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha512sum0 +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +base: 64 +assembly: xd, xs1 +encoding: + match: 000100000100-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/sha512sum0r.yaml b/arch/inst/Zk/sha512sum0r.yaml index 40dda3d20..db81f95f5 100644 --- a/arch/inst/Zk/sha512sum0r.yaml +++ b/arch/inst/Zk/sha512sum0r.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha512sum0r: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - base: 32 - assembly: xd, xs1, xs2 - encoding: - match: 0101000----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha512sum0r +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +base: 32 +assembly: xd, xs1, xs2 +encoding: + match: 0101000----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/sha512sum1.yaml b/arch/inst/Zk/sha512sum1.yaml index 9b95f7268..ddc243d7d 100644 --- a/arch/inst/Zk/sha512sum1.yaml +++ b/arch/inst/Zk/sha512sum1.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha512sum1: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - base: 64 - assembly: xd, xs1 - encoding: - match: 000100000101-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha512sum1 +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +base: 64 +assembly: xd, xs1 +encoding: + match: 000100000101-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zk/sha512sum1r.yaml b/arch/inst/Zk/sha512sum1r.yaml index 1795ec57f..b4fb002ac 100644 --- a/arch/inst/Zk/sha512sum1r.yaml +++ b/arch/inst/Zk/sha512sum1r.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sha512sum1r: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zk, Zkn, Zknh] - base: 32 - assembly: xd, xs1, xs2 - encoding: - match: 0101001----------000-----0110011 - variables: - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: true - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sha512sum1r +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zk, Zkn, Zknh] +base: 32 +assembly: xd, xs1, xs2 +encoding: + match: 0101001----------000-----0110011 + variables: + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: true +operation(): | + diff --git a/arch/inst/Zks/sm3p0.yaml b/arch/inst/Zks/sm3p0.yaml index 47ee47487..9c42bf2e9 100644 --- a/arch/inst/Zks/sm3p0.yaml +++ b/arch/inst/Zks/sm3p0.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sm3p0: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zks, Zksh] - assembly: xd, xs1 - encoding: - match: 000100001000-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sm3p0 +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zks, Zksh] +assembly: xd, xs1 +encoding: + match: 000100001000-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zks/sm3p1.yaml b/arch/inst/Zks/sm3p1.yaml index 2a21cd25d..6a51a96a1 100644 --- a/arch/inst/Zks/sm3p1.yaml +++ b/arch/inst/Zks/sm3p1.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sm3p1: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zks, Zksh] - assembly: xd, xs1 - encoding: - match: 000100001001-----001-----0010011 - variables: - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sm3p1 +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zks, Zksh] +assembly: xd, xs1 +encoding: + match: 000100001001-----001-----0010011 + variables: + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zks/sm4ed.yaml b/arch/inst/Zks/sm4ed.yaml index 24ac67f90..b8512294c 100644 --- a/arch/inst/Zks/sm4ed.yaml +++ b/arch/inst/Zks/sm4ed.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sm4ed: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zks, Zksed] - assembly: xd, xs1, xs2, bs - encoding: - match: --11000----------000-----0110011 - variables: - - name: bs - location: 31-30 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sm4ed +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zks, Zksed] +assembly: xd, xs1, xs2, bs +encoding: + match: --11000----------000-----0110011 + variables: + - name: bs + location: 31-30 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zks/sm4ks.yaml b/arch/inst/Zks/sm4ks.yaml index 2747eda6c..9854e61b5 100644 --- a/arch/inst/Zks/sm4ks.yaml +++ b/arch/inst/Zks/sm4ks.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -sm4ks: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zks, Zksed] - assembly: xd, xs1, xs2, bs - encoding: - match: --11010----------000-----0110011 - variables: - - name: bs - location: 31-30 - - name: rs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: rd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: sm4ks +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zks, Zksed] +assembly: xd, xs1, xs2, bs +encoding: + match: --11010----------000-----0110011 + variables: + - name: bs + location: 31-30 + - name: rs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vandn.vv.yaml b/arch/inst/Zvbb/vandn.vv.yaml index 2451fdd8b..27667b63e 100644 --- a/arch/inst/Zvbb/vandn.vv.yaml +++ b/arch/inst/Zvbb/vandn.vv.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vandn.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, vs1, vd - encoding: - match: 000001-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vandn.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, vs1, vd +encoding: + match: 000001-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vandn.vx.yaml b/arch/inst/Zvbb/vandn.vx.yaml index 220e7d8b3..252b3444c 100644 --- a/arch/inst/Zvbb/vandn.vx.yaml +++ b/arch/inst/Zvbb/vandn.vx.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vandn.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, xs1, vd - encoding: - match: 000001-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vandn.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, xs1, vd +encoding: + match: 000001-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vbrev.v.yaml b/arch/inst/Zvbb/vbrev.v.yaml index 5e05e5ade..175e50f27 100644 --- a/arch/inst/Zvbb/vbrev.v.yaml +++ b/arch/inst/Zvbb/vbrev.v.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vbrev.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, vd - encoding: - match: 010010------01010010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vbrev.v +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, vd +encoding: + match: 010010------01010010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vbrev8.v.yaml b/arch/inst/Zvbb/vbrev8.v.yaml index 7418c0ac2..14df079e2 100644 --- a/arch/inst/Zvbb/vbrev8.v.yaml +++ b/arch/inst/Zvbb/vbrev8.v.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vbrev8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, vd - encoding: - match: 010010------01000010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vbrev8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, vd +encoding: + match: 010010------01000010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vclz.v.yaml b/arch/inst/Zvbb/vclz.v.yaml index 24e7a1a0f..52776b73d 100644 --- a/arch/inst/Zvbb/vclz.v.yaml +++ b/arch/inst/Zvbb/vclz.v.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vclz.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, vd - encoding: - match: 010010------01100010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vclz.v +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, vd +encoding: + match: 010010------01100010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vcpop.v.yaml b/arch/inst/Zvbb/vcpop.v.yaml index 7ce032804..0145035e4 100644 --- a/arch/inst/Zvbb/vcpop.v.yaml +++ b/arch/inst/Zvbb/vcpop.v.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vcpop.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, vd - encoding: - match: 010010------01110010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vcpop.v +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, vd +encoding: + match: 010010------01110010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vctz.v.yaml b/arch/inst/Zvbb/vctz.v.yaml index 6dde98235..0b03fbad5 100644 --- a/arch/inst/Zvbb/vctz.v.yaml +++ b/arch/inst/Zvbb/vctz.v.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vctz.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, vd - encoding: - match: 010010------01101010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vctz.v +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, vd +encoding: + match: 010010------01101010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vrev8.v.yaml b/arch/inst/Zvbb/vrev8.v.yaml index 12d242602..79477546e 100644 --- a/arch/inst/Zvbb/vrev8.v.yaml +++ b/arch/inst/Zvbb/vrev8.v.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vrev8.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, vd - encoding: - match: 010010------01001010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vrev8.v +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, vd +encoding: + match: 010010------01001010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vrol.vv.yaml b/arch/inst/Zvbb/vrol.vv.yaml index 5bf9ee4c9..1c54fa104 100644 --- a/arch/inst/Zvbb/vrol.vv.yaml +++ b/arch/inst/Zvbb/vrol.vv.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vrol.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, vs1, vd - encoding: - match: 010101-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vrol.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, vs1, vd +encoding: + match: 010101-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vrol.vx.yaml b/arch/inst/Zvbb/vrol.vx.yaml index 29f747eaf..395871d9e 100644 --- a/arch/inst/Zvbb/vrol.vx.yaml +++ b/arch/inst/Zvbb/vrol.vx.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vrol.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, xs1, vd - encoding: - match: 010101-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vrol.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, xs1, vd +encoding: + match: 010101-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vror.vi.yaml b/arch/inst/Zvbb/vror.vi.yaml index ad3d0f3b4..f2dc45e56 100644 --- a/arch/inst/Zvbb/vror.vi.yaml +++ b/arch/inst/Zvbb/vror.vi.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vror.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, vd, imm - encoding: - match: 01010------------011-----1010111 - variables: - - name: imm - location: 26|19-15 - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vror.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, vd, imm +encoding: + match: 01010------------011-----1010111 + variables: + - name: imm + location: 26|19-15 + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vror.vv.yaml b/arch/inst/Zvbb/vror.vv.yaml index 879cd5c7a..5289f2f82 100644 --- a/arch/inst/Zvbb/vror.vv.yaml +++ b/arch/inst/Zvbb/vror.vv.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vror.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, vs1, vd - encoding: - match: 010100-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vror.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, vs1, vd +encoding: + match: 010100-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vror.vx.yaml b/arch/inst/Zvbb/vror.vx.yaml index 62c484d27..40a3469c7 100644 --- a/arch/inst/Zvbb/vror.vx.yaml +++ b/arch/inst/Zvbb/vror.vx.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vror.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, xs1, vd - encoding: - match: 010100-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vror.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, xs1, vd +encoding: + match: 010100-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vwsll.vi.yaml b/arch/inst/Zvbb/vwsll.vi.yaml index d616fdb87..86264addb 100644 --- a/arch/inst/Zvbb/vwsll.vi.yaml +++ b/arch/inst/Zvbb/vwsll.vi.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwsll.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, vd, imm - encoding: - match: 110101-----------011-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: zimm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwsll.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, vd, imm +encoding: + match: 110101-----------011-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: zimm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vwsll.vv.yaml b/arch/inst/Zvbb/vwsll.vv.yaml index f35666130..4e6c43fd1 100644 --- a/arch/inst/Zvbb/vwsll.vv.yaml +++ b/arch/inst/Zvbb/vwsll.vv.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwsll.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, vs1, vd - encoding: - match: 110101-----------000-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwsll.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, vs1, vd +encoding: + match: 110101-----------000-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbb/vwsll.vx.yaml b/arch/inst/Zvbb/vwsll.vx.yaml index 3361e5c8f..56c02f818 100644 --- a/arch/inst/Zvbb/vwsll.vx.yaml +++ b/arch/inst/Zvbb/vwsll.vx.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vwsll.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbb, Zvkn, Zvks] - assembly: vm, vs2, xs1, vd - encoding: - match: 110101-----------100-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vwsll.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbb, Zvkn, Zvks] +assembly: vm, vs2, xs1, vd +encoding: + match: 110101-----------100-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbc/vclmul.vv.yaml b/arch/inst/Zvbc/vclmul.vv.yaml index cc40f7b2e..bb69c75ef 100644 --- a/arch/inst/Zvbc/vclmul.vv.yaml +++ b/arch/inst/Zvbc/vclmul.vv.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vclmul.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbc, Zvkn, Zvks] - assembly: vm, vs2, vs1, vd - encoding: - match: 001100-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vclmul.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbc, Zvkn, Zvks] +assembly: vm, vs2, vs1, vd +encoding: + match: 001100-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbc/vclmul.vx.yaml b/arch/inst/Zvbc/vclmul.vx.yaml index 4de540cea..550a28392 100644 --- a/arch/inst/Zvbc/vclmul.vx.yaml +++ b/arch/inst/Zvbc/vclmul.vx.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vclmul.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbc, Zvkn, Zvks] - assembly: vm, vs2, xs1, vd - encoding: - match: 001100-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vclmul.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbc, Zvkn, Zvks] +assembly: vm, vs2, xs1, vd +encoding: + match: 001100-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbc/vclmulh.vv.yaml b/arch/inst/Zvbc/vclmulh.vv.yaml index 822773bc4..bce6dbdcf 100644 --- a/arch/inst/Zvbc/vclmulh.vv.yaml +++ b/arch/inst/Zvbc/vclmulh.vv.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vclmulh.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbc, Zvkn, Zvks] - assembly: vm, vs2, vs1, vd - encoding: - match: 001101-----------010-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vclmulh.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbc, Zvkn, Zvks] +assembly: vm, vs2, vs1, vd +encoding: + match: 001101-----------010-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvbc/vclmulh.vx.yaml b/arch/inst/Zvbc/vclmulh.vx.yaml index 14b8c33c7..5bd7e1ae3 100644 --- a/arch/inst/Zvbc/vclmulh.vx.yaml +++ b/arch/inst/Zvbc/vclmulh.vx.yaml @@ -1,28 +1,30 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vclmulh.vx: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvbc, Zvkn, Zvks] - assembly: vm, vs2, xs1, vd - encoding: - match: 001101-----------110-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vclmulh.vx +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvbc, Zvkn, Zvks] +assembly: vm, vs2, xs1, vd +encoding: + match: 001101-----------110-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvfbfmin/vfncvtbf16.f.f.w.yaml b/arch/inst/Zvfbfmin/vfncvtbf16.f.f.w.yaml index 8c4c0f7a3..b1ee08cf4 100644 --- a/arch/inst/Zvfbfmin/vfncvtbf16.f.f.w.yaml +++ b/arch/inst/Zvfbfmin/vfncvtbf16.f.f.w.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfncvtbf16.f.f.w: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zvfbfmin - assembly: vm, vs2, vd - encoding: - match: 010010------11101001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfncvtbf16.f.f.w +long_name: No synopsis available. +description: | + No description available. +definedBy: Zvfbfmin +assembly: vm, vs2, vd +encoding: + match: 010010------11101001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvfbfmin/vfwcvtbf16.f.f.v.yaml b/arch/inst/Zvfbfmin/vfwcvtbf16.f.f.v.yaml index 930df2707..0da2a89c2 100644 --- a/arch/inst/Zvfbfmin/vfwcvtbf16.f.f.v.yaml +++ b/arch/inst/Zvfbfmin/vfwcvtbf16.f.f.v.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwcvtbf16.f.f.v: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zvfbfmin - assembly: vm, vs2, vd - encoding: - match: 010010------01101001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwcvtbf16.f.f.v +long_name: No synopsis available. +description: | + No description available. +definedBy: Zvfbfmin +assembly: vm, vs2, vd +encoding: + match: 010010------01101001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvfbfwma/vfwmaccbf16.vf.yaml b/arch/inst/Zvfbfwma/vfwmaccbf16.vf.yaml index 56943c085..a80a38513 100644 --- a/arch/inst/Zvfbfwma/vfwmaccbf16.vf.yaml +++ b/arch/inst/Zvfbfwma/vfwmaccbf16.vf.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwmaccbf16.vf: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zvfbfwma - assembly: vm, vs2, xs1, vd - encoding: - match: 111011-----------101-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: rs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwmaccbf16.vf +long_name: No synopsis available. +description: | + No description available. +definedBy: Zvfbfwma +assembly: vm, vs2, xs1, vd +encoding: + match: 111011-----------101-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: rs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvfbfwma/vfwmaccbf16.vv.yaml b/arch/inst/Zvfbfwma/vfwmaccbf16.vv.yaml index 1d258124b..d50b3db0d 100644 --- a/arch/inst/Zvfbfwma/vfwmaccbf16.vv.yaml +++ b/arch/inst/Zvfbfwma/vfwmaccbf16.vv.yaml @@ -1,27 +1,29 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vfwmaccbf16.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zvfbfwma - assembly: vm, vs2, vs1, vd - encoding: - match: 111011-----------001-----1010111 - variables: - - name: vm - location: 25-25 - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vfwmaccbf16.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: Zvfbfwma +assembly: vm, vs2, vs1, vd +encoding: + match: 111011-----------001-----1010111 + variables: + - name: vm + location: 25-25 + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkg/vghsh.vv.yaml b/arch/inst/Zvkg/vghsh.vv.yaml index 6621787d8..ffaa78827 100644 --- a/arch/inst/Zvkg/vghsh.vv.yaml +++ b/arch/inst/Zvkg/vghsh.vv.yaml @@ -1,25 +1,27 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vghsh.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zvkg - assembly: vs2, vs1, vd - encoding: - match: 1011001----------010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vghsh.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: Zvkg +assembly: vs2, vs1, vd +encoding: + match: 1011001----------010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkg/vgmul.vv.yaml b/arch/inst/Zvkg/vgmul.vv.yaml index 54471d29a..a1d2dc1ed 100644 --- a/arch/inst/Zvkg/vgmul.vv.yaml +++ b/arch/inst/Zvkg/vgmul.vv.yaml @@ -1,23 +1,25 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vgmul.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: Zvkg - assembly: vs2, vd - encoding: - match: 1010001-----10001010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vgmul.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: Zvkg +assembly: vs2, vd +encoding: + match: 1010001-----10001010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vaesdf.vs.yaml b/arch/inst/Zvkn/vaesdf.vs.yaml index ca1f5b7ff..0996304f1 100644 --- a/arch/inst/Zvkn/vaesdf.vs.yaml +++ b/arch/inst/Zvkn/vaesdf.vs.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaesdf.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvkned] - assembly: vs2, vd - encoding: - match: 1010011-----00001010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaesdf.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvkned] +assembly: vs2, vd +encoding: + match: 1010011-----00001010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vaesdf.vv.yaml b/arch/inst/Zvkn/vaesdf.vv.yaml index 61ebaeffc..aa4a6c059 100644 --- a/arch/inst/Zvkn/vaesdf.vv.yaml +++ b/arch/inst/Zvkn/vaesdf.vv.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaesdf.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvkned] - assembly: vs2, vd - encoding: - match: 1010001-----00001010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaesdf.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvkned] +assembly: vs2, vd +encoding: + match: 1010001-----00001010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vaesdm.vs.yaml b/arch/inst/Zvkn/vaesdm.vs.yaml index 24154a4ef..68f3a3004 100644 --- a/arch/inst/Zvkn/vaesdm.vs.yaml +++ b/arch/inst/Zvkn/vaesdm.vs.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaesdm.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvkned] - assembly: vs2, vd - encoding: - match: 1010011-----00000010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaesdm.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvkned] +assembly: vs2, vd +encoding: + match: 1010011-----00000010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vaesdm.vv.yaml b/arch/inst/Zvkn/vaesdm.vv.yaml index b9bbc6c9c..c3c043f20 100644 --- a/arch/inst/Zvkn/vaesdm.vv.yaml +++ b/arch/inst/Zvkn/vaesdm.vv.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaesdm.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvkned] - assembly: vs2, vd - encoding: - match: 1010001-----00000010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaesdm.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvkned] +assembly: vs2, vd +encoding: + match: 1010001-----00000010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vaesef.vs.yaml b/arch/inst/Zvkn/vaesef.vs.yaml index a22ce5bcf..c335467b3 100644 --- a/arch/inst/Zvkn/vaesef.vs.yaml +++ b/arch/inst/Zvkn/vaesef.vs.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaesef.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvkned] - assembly: vs2, vd - encoding: - match: 1010011-----00011010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaesef.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvkned] +assembly: vs2, vd +encoding: + match: 1010011-----00011010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vaesef.vv.yaml b/arch/inst/Zvkn/vaesef.vv.yaml index 8495cca4f..07d123a8f 100644 --- a/arch/inst/Zvkn/vaesef.vv.yaml +++ b/arch/inst/Zvkn/vaesef.vv.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaesef.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvkned] - assembly: vs2, vd - encoding: - match: 1010001-----00011010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaesef.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvkned] +assembly: vs2, vd +encoding: + match: 1010001-----00011010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vaesem.vs.yaml b/arch/inst/Zvkn/vaesem.vs.yaml index f9c8a99dd..574400752 100644 --- a/arch/inst/Zvkn/vaesem.vs.yaml +++ b/arch/inst/Zvkn/vaesem.vs.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaesem.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvkned] - assembly: vs2, vd - encoding: - match: 1010011-----00010010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaesem.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvkned] +assembly: vs2, vd +encoding: + match: 1010011-----00010010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vaesem.vv.yaml b/arch/inst/Zvkn/vaesem.vv.yaml index cf2fb6cc4..cb29270c0 100644 --- a/arch/inst/Zvkn/vaesem.vv.yaml +++ b/arch/inst/Zvkn/vaesem.vv.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaesem.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvkned] - assembly: vs2, vd - encoding: - match: 1010001-----00010010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaesem.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvkned] +assembly: vs2, vd +encoding: + match: 1010001-----00010010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vaeskf1.vi.yaml b/arch/inst/Zvkn/vaeskf1.vi.yaml index d3b688f78..acfc9c1f4 100644 --- a/arch/inst/Zvkn/vaeskf1.vi.yaml +++ b/arch/inst/Zvkn/vaeskf1.vi.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaeskf1.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvkned] - assembly: vs2, vd, imm - encoding: - match: 1000101----------010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: zimm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaeskf1.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvkned] +assembly: vs2, vd, imm +encoding: + match: 1000101----------010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: zimm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vaeskf2.vi.yaml b/arch/inst/Zvkn/vaeskf2.vi.yaml index 4830e4f37..bb5e68084 100644 --- a/arch/inst/Zvkn/vaeskf2.vi.yaml +++ b/arch/inst/Zvkn/vaeskf2.vi.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaeskf2.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvkned] - assembly: vs2, vd, imm - encoding: - match: 1010101----------010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: zimm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaeskf2.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvkned] +assembly: vs2, vd, imm +encoding: + match: 1010101----------010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: zimm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vaesz.vs.yaml b/arch/inst/Zvkn/vaesz.vs.yaml index a0454556f..8d471a615 100644 --- a/arch/inst/Zvkn/vaesz.vs.yaml +++ b/arch/inst/Zvkn/vaesz.vs.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vaesz.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvkned] - assembly: vs2, vd - encoding: - match: 1010011-----00111010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vaesz.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvkned] +assembly: vs2, vd +encoding: + match: 1010011-----00111010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vsha2ch.vv.yaml b/arch/inst/Zvkn/vsha2ch.vv.yaml index 30112ce04..c7c307289 100644 --- a/arch/inst/Zvkn/vsha2ch.vv.yaml +++ b/arch/inst/Zvkn/vsha2ch.vv.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsha2ch.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvknha, Zvknhb] - assembly: vs2, vs1, vd - encoding: - match: 1011101----------010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsha2ch.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvknha, Zvknhb] +assembly: vs2, vs1, vd +encoding: + match: 1011101----------010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vsha2cl.vv.yaml b/arch/inst/Zvkn/vsha2cl.vv.yaml index 2824416f4..af0a15046 100644 --- a/arch/inst/Zvkn/vsha2cl.vv.yaml +++ b/arch/inst/Zvkn/vsha2cl.vv.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsha2cl.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvknha, Zvknhb] - assembly: vs2, vs1, vd - encoding: - match: 1011111----------010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsha2cl.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvknha, Zvknhb] +assembly: vs2, vs1, vd +encoding: + match: 1011111----------010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvkn/vsha2ms.vv.yaml b/arch/inst/Zvkn/vsha2ms.vv.yaml index 4355c230e..3ed25d80f 100644 --- a/arch/inst/Zvkn/vsha2ms.vv.yaml +++ b/arch/inst/Zvkn/vsha2ms.vv.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsha2ms.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvkn, Zvknha, Zvknhb] - assembly: vs2, vs1, vd - encoding: - match: 1011011----------010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsha2ms.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvkn, Zvknha, Zvknhb] +assembly: vs2, vs1, vd +encoding: + match: 1011011----------010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvks/vsm3c.vi.yaml b/arch/inst/Zvks/vsm3c.vi.yaml index a7920c09a..ce7ee47ad 100644 --- a/arch/inst/Zvks/vsm3c.vi.yaml +++ b/arch/inst/Zvks/vsm3c.vi.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsm3c.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvks, Zvksh] - assembly: vs2, vd, imm - encoding: - match: 1010111----------010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: zimm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsm3c.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvks, Zvksh] +assembly: vs2, vd, imm +encoding: + match: 1010111----------010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: zimm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvks/vsm3me.vv.yaml b/arch/inst/Zvks/vsm3me.vv.yaml index a4c8393a8..083bc526b 100644 --- a/arch/inst/Zvks/vsm3me.vv.yaml +++ b/arch/inst/Zvks/vsm3me.vv.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsm3me.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvks, Zvksh] - assembly: vs2, vs1, vd - encoding: - match: 1000001----------010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vs1 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsm3me.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvks, Zvksh] +assembly: vs2, vs1, vd +encoding: + match: 1000001----------010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vs1 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvks/vsm4k.vi.yaml b/arch/inst/Zvks/vsm4k.vi.yaml index 30451cc36..fb641d68f 100644 --- a/arch/inst/Zvks/vsm4k.vi.yaml +++ b/arch/inst/Zvks/vsm4k.vi.yaml @@ -1,26 +1,28 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsm4k.vi: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvks, Zvksed] - assembly: vs2, vd, imm - encoding: - match: 1000011----------010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: zimm5 - location: 19-15 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsm4k.vi +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvks, Zvksed] +assembly: vs2, vd, imm +encoding: + match: 1000011----------010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: zimm5 + location: 19-15 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvks/vsm4r.vs.yaml b/arch/inst/Zvks/vsm4r.vs.yaml index 1632907cd..9fa81255a 100644 --- a/arch/inst/Zvks/vsm4r.vs.yaml +++ b/arch/inst/Zvks/vsm4r.vs.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsm4r.vs: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvks, Zvksed] - assembly: vs2, vd - encoding: - match: 1010011-----10000010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsm4r.vs +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvks, Zvksed] +assembly: vs2, vd +encoding: + match: 1010011-----10000010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/inst/Zvks/vsm4r.vv.yaml b/arch/inst/Zvks/vsm4r.vv.yaml index ebd8aa3be..40f6c8b67 100644 --- a/arch/inst/Zvks/vsm4r.vv.yaml +++ b/arch/inst/Zvks/vsm4r.vv.yaml @@ -1,24 +1,26 @@ # yaml-language-server: $schema=../../../schemas/inst_schema.json -vsm4r.vv: - long_name: No synopsis available. - description: | - No description available. - definedBy: - anyOf: [Zvks, Zvksed] - assembly: vs2, vd - encoding: - match: 1010001-----10000010-----1110111 - variables: - - name: vs2 - location: 24-20 - - name: vd - location: 11-7 - access: - s: always - u: always - vs: always - vu: always - data_independent_timing: false - operation(): | - +$schema: "inst_schema.json#" +kind: instruction +name: vsm4r.vv +long_name: No synopsis available. +description: | + No description available. +definedBy: + anyOf: [Zvks, Zvksed] +assembly: vs2, vd +encoding: + match: 1010001-----10000010-----1110111 + variables: + - name: vs2 + location: 24-20 + - name: vd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +data_independent_timing: false +operation(): | + diff --git a/arch/profile_release/RVA20.yaml b/arch/profile_release/RVA20.yaml index 195f603c6..6be79e41d 100644 --- a/arch/profile_release/RVA20.yaml +++ b/arch/profile_release/RVA20.yaml @@ -43,7 +43,7 @@ RVA20: most important profile within application processors in terms of the amount of software that targets this profile. extensions: - $inherits: "RVI20.yaml#/RVI20/profiles/RVI20U64/extensions" + $inherits: "profile_release/RVI20.yaml#/RVI20/profiles/RVI20U64/extensions" $remove: Zifencei # Not allowed as an option for Unpriv ISA (only available in Priv ISA). A: presence: mandatory diff --git a/arch/profile_release/RVA22.yaml b/arch/profile_release/RVA22.yaml index c564c915b..327ff31aa 100644 --- a/arch/profile_release/RVA22.yaml +++ b/arch/profile_release/RVA22.yaml @@ -43,7 +43,7 @@ RVA22: most important profile within application processors in terms of the amount of software that targets this profile. extensions: - $inherits: "RVA20.yaml#/RVA20/profiles/RVA20U64/extensions" + $inherits: "profile_release/RVA20.yaml#/RVA20/profiles/RVA20U64/extensions" Zihpm: presence: mandatory version: "= 2.0" @@ -167,7 +167,7 @@ RVA22: processors. RVA22S64 is based on privileged architecture version 1.12. extensions: - $inherits: "RVA20.yaml#/RVA20/profiles/RVA20S64/extensions" + $inherits: "profile_release/RVA20.yaml#/RVA20/profiles/RVA20S64/extensions" S: presence: mandatory version: "= 1.12" diff --git a/backends/arch_gen/lib/arch_gen.rb b/backends/arch_gen/lib/arch_gen.rb index dd40f6f26..6018fd65c 100644 --- a/backends/arch_gen/lib/arch_gen.rb +++ b/backends/arch_gen/lib/arch_gen.rb @@ -53,8 +53,8 @@ def gen_params_schema ext_name = ext["name"] gen_ext_path = @gen_dir / "arch" / "ext" / "#{ext_name}.yaml" ext_yaml = YAML.load_file gen_ext_path.to_s - unless ext_yaml[ext_name]["params"].nil? - ext_yaml[ext_name]["params"].each do |param_name, param_data| + unless ext_yaml["params"].nil? + ext_yaml["params"].each do |param_name, param_data| schema["properties"]["params"]["required"] << param_name schema["properties"]["params"]["properties"][param_name] = { "description" => param_data["description"] @@ -147,8 +147,8 @@ def params_extra_validation ext_name = ext["name"] gen_ext_path = @gen_dir / "arch" / "ext" / "#{ext_name}.yaml" ext_yaml = YAML.load_file gen_ext_path.to_s - unless ext_yaml[ext_name]["params"].nil? - ext_yaml[ext_name]["params"].each do |param_name, param_data| + unless ext_yaml["params"].nil? + ext_yaml["params"].each do |param_name, param_data| next unless param_data.key?("extra_validation") begin eval_context.class_eval param_data["extra_validation"] @@ -273,21 +273,15 @@ def implemented_extensions # Generate the config-specific, unified architecture spec data structure # def gen_arch_def - csr_hash = Dir.glob(@gen_dir / "arch" / "csr" / "**" / "*.yaml").map do |f| - csr_obj = YamlLoader.load(f, permitted_classes:[Date]) - csr_name = csr_obj.keys[0] - [csr_name, csr_obj[csr_name]] - end.to_h - inst_hash = Dir.glob(@gen_dir / "arch" / "inst" / "**" / "*.yaml").map do |f| - inst_obj = YamlLoader.load(f, permitted_classes:[Date]) - inst_name = inst_obj.keys[0] - [inst_name, inst_obj[inst_name]] - end.to_h - ext_hash = Dir.glob(@gen_dir / "arch" / "ext" / "**" / "*.yaml").map do |f| - ext_obj = YamlLoader.load(f, permitted_classes:[Date]) - ext_name = ext_obj.keys[0] - [ext_name, ext_obj[ext_name]] - end.to_h + csr_ary = Dir.glob(@gen_dir / "arch" / "csr" / "**" / "*.yaml").map do |f| + YamlLoader.load(f, permitted_classes:[Date]) + end + inst_ary = Dir.glob(@gen_dir / "arch" / "inst" / "**" / "*.yaml").map do |f| + YamlLoader.load(f, permitted_classes:[Date]) + end + ext_ary = Dir.glob(@gen_dir / "arch" / "ext" / "**" / "*.yaml").map do |f| + YamlLoader.load(f, permitted_classes:[Date]) + end profile_class_hash = Dir.glob($root / "arch" / "profile_class" / "**" / "*.yaml").map do |f| profile_class_obj = YamlLoader.load(f, permitted_classes:[Date]) profile_class_name = profile_class_obj.keys[0] @@ -302,20 +296,16 @@ def gen_arch_def profile_release_obj[profile_release_name]["__source"] = f [profile_release_name, profile_release_obj[profile_release_name]] end.to_h - cert_class_hash = Dir.glob($root / "arch" / "certificate_class" / "**" / "*.yaml").map do |f| + cert_class_ary = Dir.glob($root / "arch" / "certificate_class" / "**" / "*.yaml").map do |f| cert_class_obj = YamlLoader.load(f, permitted_classes:[Date]) - cert_class_name = cert_class_obj.keys[0] - cert_class_obj[cert_class_name]["name"] = cert_class_name - cert_class_obj[cert_class_name]["__source"] = f - [cert_class_name, cert_class_obj[cert_class_name]] - end.to_h - cert_model_hash = Dir.glob($root / "arch" / "certificate_model" / "**" / "*.yaml").map do |f| + cert_class_obj["__source"] = f + cert_class_obj + end + cert_model_ary = Dir.glob($root / "arch" / "certificate_model" / "**" / "*.yaml").map do |f| cert_model_obj = YamlLoader.load(f, permitted_classes:[Date]) - cert_model_name = cert_model_obj.keys[0] - cert_model_obj[cert_model_name]["name"] = cert_model_name - cert_model_obj[cert_model_name]["__source"] = f - [cert_model_name, cert_model_obj[cert_model_name]] - end.to_h + cert_model_obj["__source"] = f + cert_model_obj + end manual_hash = {} Dir.glob($root / "arch" / "manual" / "**" / "contents.yaml").map do |f| manual_version = YamlLoader.load(f, permitted_classes:[Date]) @@ -340,16 +330,16 @@ def gen_arch_def arch_def = { "type" => @cfg_opts["type"], "params" => params, - "instructions" => inst_hash, + "instructions" => inst_ary, "implemented_instructions" => @implemented_instructions, - "extensions" => ext_hash, + "extensions" => ext_ary, "implemented_extensions" => @implemented_extensions, - "csrs" => csr_hash, + "csrs" => csr_ary, "implemented_csrs" => @implemented_csrs, "profile_classes" => profile_class_hash, "profile_releases" => profile_release_hash, - "certificate_classes" => cert_class_hash, - "certificate_models" => cert_model_hash, + "certificate_classes" => cert_class_ary, + "certificate_models" => cert_model_ary, "manuals" => manual_hash } @@ -630,12 +620,11 @@ def maybe_add_csr(csr_name, extra_env = {}) end # get the csr data (not including the name key), which is redundant at this point - csr_data = YAML.load_file(merged_path)[csr_name] - csr_data["name"] = csr_name + csr_data = YAML.load_file(merged_path) csr_data["fields"].each { |n, f| f["name"] = n } csr_data["__source"] = og_path.to_s - csr_yaml = YAML.dump({ csr_name => csr_data}) + csr_yaml = YAML.dump(csr_data) begin csr_data = @validator.validate_str(csr_yaml, type: :csr) rescue Validator::SchemaValidationError => e @@ -643,7 +632,7 @@ def maybe_add_csr(csr_name, extra_env = {}) raise e end - csr_obj = Csr.new(csr_data[csr_name]) + csr_obj = Csr.new(csr_data) arch_def_mock = Object.new arch_def_mock.define_singleton_method(:fully_configured?) { true } pos_xlen_local = possible_xlens @@ -714,10 +703,9 @@ def maybe_add_ext(ext_name) merged_path = gen_merged_def(:ext, arch_path, arch_overlay_path) yaml_contents = YAML.load_file(merged_path) - raise "In #{merged_path}, key does not match file name" unless yaml_contents.key?(ext_name) + raise "In #{merged_path}, key does not match file name" unless yaml_contents["name"] == ext_name - ext_obj = yaml_contents[ext_name] - ext_obj["name"] = ext_name + ext_obj = yaml_contents @implied_ext_map ||= {} @required_ext_map ||= {} @@ -764,7 +752,7 @@ def maybe_add_ext(ext_name) gen_ext_path = @gen_dir / "arch" / "ext" / "#{ext_name}.yaml" FileUtils.mkdir_p gen_ext_path.dirname - gen_ext_path.write YAML.dump({ ext_name => ext_obj }) + gen_ext_path.write YAML.dump(ext_obj) end private :maybe_add_ext @@ -876,13 +864,9 @@ def maybe_add_inst(inst_name, extra_env = {}) # get the inst data (not including the name key), which is redundant at this point inst_data = YAML.load_file(merged_path) - raise "The first and only key of #{arch_path} must be '#{inst_name}" unless inst_data.key?(inst_name) - inst_data = inst_data[inst_name] - - inst_data["name"] = inst_name inst_data["__source"] = og_path.to_s - inst_yaml = YAML.dump({ inst_name => inst_data}) + inst_yaml = YAML.dump(inst_data) begin inst_data = @validator.validate_str(inst_yaml, type: :inst) rescue Validator::SchemaValidationError => e @@ -890,7 +874,7 @@ def maybe_add_inst(inst_name, extra_env = {}) raise e end - inst_obj = Instruction.new(inst_data[inst_name], nil) + inst_obj = Instruction.new(inst_data, nil) possible_xlens = [params["XLEN"]] if @cfg_impl_ext.any? { |e| e[0] == "S" } possible_xlens << 32 if [32, 3264].include?(params["SXLEN"]) @@ -923,11 +907,6 @@ def maybe_add_inst(inst_name, extra_env = {}) gen_inst_path = @gen_dir / "arch" / "inst" / inst_obj.primary_defined_by / "#{inst_name}.yaml" FileUtils.mkdir_p gen_inst_path.dirname gen_inst_path.write inst_yaml - - - # @instructions << inst_def - # @inst_hash ||= {} - # @inst_hash[inst_name] = @instructions.last end private :maybe_add_inst diff --git a/backends/arch_gen/tasks.rake b/backends/arch_gen/tasks.rake index 482548b8d..6515e54f5 100644 --- a/backends/arch_gen/tasks.rake +++ b/backends/arch_gen/tasks.rake @@ -33,31 +33,25 @@ file "#{$root}/.stamps/arch-gen.stamp" => ( __FILE__ ] + Dir.glob($root / "arch" / "**" / "*.yaml") ) do |t| - csr_hash = Dir.glob($root / "arch" / "csr" / "**" / "*.yaml").map do |f| + csr_ary = Dir.glob($root / "arch" / "csr" / "**" / "*.yaml").map do |f| csr_obj = YamlLoader.load(f, permitted_classes:[Date]) - csr_name = csr_obj.keys[0] - csr_obj[csr_name]["name"] = csr_name - csr_obj[csr_name]["fields"].map do |k, v| + csr_obj["fields"].map do |k, v| v["name"] = k [k, v] end - csr_obj[csr_name]["__source"] = f - [csr_name, csr_obj[csr_name]] - end.to_h - inst_hash = Dir.glob($root / "arch" / "inst" / "**" / "*.yaml").map do |f| + csr_obj["__source"] = f + csr_obj + end + inst_ary = Dir.glob($root / "arch" / "inst" / "**" / "*.yaml").map do |f| inst_obj = YamlLoader.load(f, permitted_classes:[Date]) - inst_name = inst_obj.keys[0] - inst_obj[inst_name]["name"] = inst_name - inst_obj[inst_name]["__source"] = f - [inst_name, inst_obj[inst_name]] - end.to_h - ext_hash = Dir.glob($root / "arch" / "ext" / "**" / "*.yaml").map do |f| + inst_obj["__source"] = f + inst_obj + end + ext_ary = Dir.glob($root / "arch" / "ext" / "**" / "*.yaml").map do |f| ext_obj = YamlLoader.load(f, permitted_classes:[Date]) - ext_name = ext_obj.keys[0] - ext_obj[ext_name]["name"] = ext_name - ext_obj[ext_name]["__source"] = f - [ext_name, ext_obj[ext_name]] - end.to_h + ext_obj["__source"] = f + ext_obj + end profile_class_hash = Dir.glob($root / "arch" / "profile_class" / "**" / "*.yaml").map do |f| profile_class_obj = YamlLoader.load(f, permitted_classes:[Date]) profile_class_name = profile_class_obj.keys[0] @@ -72,20 +66,16 @@ file "#{$root}/.stamps/arch-gen.stamp" => ( profile_release_obj[profile_release_name]["__source"] = f [profile_release_name, profile_release_obj[profile_release_name]] end.to_h - cert_class_hash = Dir.glob($root / "arch" / "certificate_class" / "**" / "*.yaml").map do |f| + cert_class_ary = Dir.glob($root / "arch" / "certificate_class" / "**" / "*.yaml").map do |f| cert_class_obj = YamlLoader.load(f, permitted_classes:[Date]) - cert_class_name = cert_class_obj.keys[0] - cert_class_obj[cert_class_name]["name"] = cert_class_name - cert_class_obj[cert_class_name]["__source"] = f - [cert_class_name, cert_class_obj[cert_class_name]] - end.to_h - cert_model_hash = Dir.glob($root / "arch" / "certificate_model" / "**" / "*.yaml").map do |f| + cert_class_obj["__source"] = f + cert_class_obj + end + cert_model_ary = Dir.glob($root / "arch" / "certificate_model" / "**" / "*.yaml").map do |f| cert_model_obj = YamlLoader.load(f, permitted_classes:[Date]) - cert_model_name = cert_model_obj.keys[0] - cert_model_obj[cert_model_name]["name"] = cert_model_name - cert_model_obj[cert_model_name]["__source"] = f - [cert_model_name, cert_model_obj[cert_model_name]] - end.to_h + cert_model_obj["__source"] = f + cert_model_obj + end manual_hash = {} Dir.glob($root / "arch" / "manual" / "**" / "contents.yaml").map do |f| manual_version = YamlLoader.load(f, permitted_classes:[Date]) @@ -109,13 +99,13 @@ file "#{$root}/.stamps/arch-gen.stamp" => ( arch_def = { "type" => "unconfigured", - "instructions" => inst_hash, - "extensions" => ext_hash, - "csrs" => csr_hash, + "instructions" => inst_ary, + "extensions" => ext_ary, + "csrs" => csr_ary, "profile_classes" => profile_class_hash, "profile_releases" => profile_release_hash, - "certificate_classes" => cert_class_hash, - "certificate_models" => cert_model_hash, + "certificate_classes" => cert_class_ary, + "certificate_models" => cert_model_ary, "manuals" => manual_hash } diff --git a/backends/certificate_doc/tasks.rake b/backends/certificate_doc/tasks.rake index d95e993f4..106c38c11 100644 --- a/backends/certificate_doc/tasks.rake +++ b/backends/certificate_doc/tasks.rake @@ -12,14 +12,15 @@ CERT_DOC_DIR = Pathname.new "#{$root}/backends/certificate_doc" Dir.glob("#{$root}/arch/certificate_model/*.yaml") do |f| cert_model_name = File.basename(f, ".yaml") cert_model_obj = YAML.load_file(f, permitted_classes: [Date]) - raise "Ill-formed certificate model file #{f}: missing 'class' field" if cert_model_obj.dig(cert_model_name, 'class').nil? + cert_class_name = File.basename(cert_model_obj['class']['$ref'].split("#")[0], ".yaml") + raise "Ill-formed certificate model file #{f}: missing 'class' field" if cert_model_obj['class'].nil? - base = cert_model_obj[cert_model_name]["base"] + base = cert_model_obj["base"] raise "Missing certificate model base" if base.nil? file "#{$root}/gen/certificate_doc/adoc/#{cert_model_name}.adoc" => [ "#{$root}/arch/certificate_model/#{cert_model_name}.yaml", - "#{$root}/arch/certificate_class/#{cert_model_obj[cert_model_name]['class']}.yaml", + "#{$root}/arch/certificate_class/#{cert_class_name}.yaml", "#{CERT_DOC_DIR}/templates/certificate.adoc.erb", __FILE__, "#{$root}/.stamps/arch-gen-_#{base}.stamp" diff --git a/cfgs/generic_rv64/arch_overlay/csr/marchid.yaml b/cfgs/generic_rv64/arch_overlay/csr/marchid.yaml index 4d531edde..284145e3e 100644 --- a/cfgs/generic_rv64/arch_overlay/csr/marchid.yaml +++ b/cfgs/generic_rv64/arch_overlay/csr/marchid.yaml @@ -1,6 +1,5 @@ --- # Overrides the value of marchid.Architecture to 0xcafebabe -marchid: - fields: - Architecture: - description: Custom overlay description +fields: + Architecture: + description: Custom overlay description diff --git a/cfgs/generic_rv64/arch_overlay/csr/mcustom0.yaml b/cfgs/generic_rv64/arch_overlay/csr/mcustom0.yaml index b627ec8d3..f0f01d376 100644 --- a/cfgs/generic_rv64/arch_overlay/csr/mcustom0.yaml +++ b/cfgs/generic_rv64/arch_overlay/csr/mcustom0.yaml @@ -1,11 +1,13 @@ # yaml-language-server: $schema=../../../../schemas/csr_schema.json --- -mcustom0: - long_name: Custom CSR 0 - address: 0xfc0 - length: 64 - priv_mode: M - definedBy: Xcustom - description: An example custom CSR - fields: {} +$schema: "csr_schema.json#" +kind: csr +name: mcustom0 +long_name: Custom CSR 0 +address: 0xfc0 +length: 64 +priv_mode: M +definedBy: Xcustom +description: An example custom CSR +fields: {} diff --git a/cfgs/generic_rv64/arch_overlay/ext/Xcustom.yaml b/cfgs/generic_rv64/arch_overlay/ext/Xcustom.yaml index 2284a6581..80aa49d40 100644 --- a/cfgs/generic_rv64/arch_overlay/ext/Xcustom.yaml +++ b/cfgs/generic_rv64/arch_overlay/ext/Xcustom.yaml @@ -1,10 +1,12 @@ --- -Xcustom: - long_name: A new custom extension! - type: unprivileged - versions: - - version: "0.1.0" - ratification_date: null - state: development - description: | - A new custom extension! +$schema: "ext_schema.json#" +kind: extension +name: Xcustom +long_name: A new custom extension! +type: unprivileged +versions: +- version: "0.1.0" + ratification_date: null + state: development +description: | + A new custom extension! diff --git a/lib/arch_def.rb b/lib/arch_def.rb index b01c9fa16..5c16477a9 100644 --- a/lib/arch_def.rb +++ b/lib/arch_def.rb @@ -357,7 +357,7 @@ def extensions return @extensions unless @extensions.nil? @extensions = [] - @arch_def["extensions"].each_value do |ext_data| + @arch_def["extensions"].each do |ext_data| @extensions << Extension.new(ext_data, self) end @extensions @@ -517,7 +517,7 @@ def param(name) def csrs return @csrs unless @csrs.nil? - @csrs = @arch_def["csrs"].map do |_csr_name, csr_data| + @csrs = @arch_def["csrs"].map do |csr_data| Csr.new(csr_data) end end @@ -549,7 +549,7 @@ def csr(csr_name) def instructions return @instructions unless @instructions.nil? - @instructions = @arch_def["instructions"].map do |_inst_name, inst_data| + @instructions = @arch_def["instructions"].map do |inst_data| Instruction.new(inst_data, self) end @@ -720,7 +720,7 @@ def cert_classes return @cert_classes unless @cert_classes.nil? @cert_classes = [] - @arch_def["certificate_classes"].each_value do |cc_data| + @arch_def["certificate_classes"].each do |cc_data| @cert_classes << CertClass.new(cc_data, self) end @cert_classes @@ -745,7 +745,7 @@ def cert_models return @cert_models unless @cert_models.nil? @cert_models = [] - @arch_def["certificate_models"].each_value do |cm_data| + @arch_def["certificate_models"].each do |cm_data| @cert_models << CertModel.new(cm_data, self) end @cert_models @@ -1046,14 +1046,14 @@ def implemented_interrupt_codes def unconfigured_data { "type" => "partially configured", - "instructions" => instructions.map { |i| [i.name, i.data] }.to_h, - "extensions" => extensions.map.map { |e| [e.name, e.data] }.to_h, - "csrs" => csrs.map { |c| [c.name, c.data] }.to_h, + "instructions" => instructions.map(&:data), + "extensions" => extensions.map.map(&:data), + "csrs" => csrs.map(&:data), "profile_classes" => profile_classes.map { |f| [f.name, f.data] }.to_h, "profile_releases" => profile_releases.map { |p| [p.name, p.data] }.to_h, "manuals" => manuals.map { |m| [m.name, m.data] }.to_h, - "certificate_classes" => cert_classes.map { |f| [f.name, f.data] }.to_h, - "certificate_models" => cert_models.map { |c| [c.name, c.data] }.to_h + "certificate_classes" => cert_classes.map(&:data), + "certificate_models" => cert_models.map(&:data) } end diff --git a/lib/arch_obj_models/certificate.rb b/lib/arch_obj_models/certificate.rb index d76809970..865ae8fa8 100644 --- a/lib/arch_obj_models/certificate.rb +++ b/lib/arch_obj_models/certificate.rb @@ -48,7 +48,7 @@ def tsc_profile # @return [CertClass] The certification class that this model belongs to. def cert_class - cert_class = @arch_def.cert_class(@data["class"]) + cert_class = @arch_def.cert_class(File.basename(@data["class"]['$ref'].split("#")[0], ".yaml")) raise "No certificate class named '#{@data["class"]}'" if cert_class.nil? cert_class diff --git a/lib/arch_obj_models/obj.rb b/lib/arch_obj_models/obj.rb index 04fe64a78..69cb76387 100644 --- a/lib/arch_obj_models/obj.rb +++ b/lib/arch_obj_models/obj.rb @@ -182,7 +182,12 @@ def source_line(*path) path_idx = 0 Psych.parse_stream(File.read(yaml_filename), filename: yaml_filename) do |doc| mapping = doc.children[0] - data = mapping.children[1] + data = + if mapping.children.size == 2 + mapping.children[1] + else + mapping + end while path_idx < path.size idx = 0 while idx < data.children.size diff --git a/lib/validate.rb b/lib/validate.rb index bac6ffda3..c2215b433 100644 --- a/lib/validate.rb +++ b/lib/validate.rb @@ -22,7 +22,8 @@ class Validator ext: $root / "schemas" / "ext_schema.json", csr: $root / "schemas" / "csr_schema.json", cfg_impl_ext: $root / "schemas" / "implemented_exts_schema.json", - manual_version: $root / "schemas" / "manual_version_schema.json" + manual_version: $root / "schemas" / "manual_version_schema.json", + cert_class: $root / "schemas" / "cert_class_schema.json" }.freeze # types of objects that can be validated @@ -58,9 +59,10 @@ class SchemaValidationError < ::StandardError # create a new SchemaValidationError # # @param result [JsonSchemer::Result] JsonSchemer result - def initialize(result) + def initialize(path, result) + msg = "While validating #{path}:\n\n" nerrors = result.count - msg = +"#{nerrors} error(s) during validations\n\n" + msg << "#{nerrors} error(s) during validations\n\n" result.to_a.each do |r| msg << if r["type"] == "required" && !r.dig("details", "missing_keys").nil? @@ -131,7 +133,7 @@ def initialize # @param type [Symbol] Type of the object (One of TYPES) # @raise [SchemaValidationError] if the str is not valid against the type schema # @see TYPES - def validate_str(str, type: nil, schema_path: nil) + def validate_str(str, type: nil, schema_path: nil, path: nil) raise "Invalid type #{type}" unless TYPES.any?(type) || !schema_path.nil? begin @@ -162,7 +164,7 @@ def validate_str(str, type: nil, schema_path: nil) ) end - raise SchemaValidationError, schema.validate(jsonified_obj) unless schema.valid?(jsonified_obj) + raise SchemaValidationError.new(path, schema.validate(jsonified_obj)) unless schema.valid?(jsonified_obj) jsonified_obj end @@ -195,17 +197,19 @@ def validate(path, type: nil) type = :csr when %r{.*arch/manual/.*/.*contents\.yaml$} type = :manual_version + when %r{.*arch/certificate_class/.*\.yaml$} + type = :cert_class else warn "Cannot determine type from YAML path '#{path}'; skipping" return end end begin - obj = validate_str(File.read(path.to_s), type:, schema_path:) + obj = validate_str(File.read(path.to_s), path:, type:, schema_path:) - # check that the top key matches the filename - if [:inst, :ext, :csr].include?(type) && obj.keys.first != File.basename(path, ".yaml").to_s - raise ValidationError, "In #{path}, top key '#{obj.keys.first}' does not match filename '#{File.basename(path)}'" + # check that the name matches the filename + if [:inst, :csr, :ext, :cert_class].include?(type) && obj["name"] != File.basename(path, ".yaml").to_s + raise ValidationError, "In #{path}, object name '#{obj.keys.first}' does not match filename '#{File.basename(path)}'" end obj rescue Psych::SyntaxError => e @@ -262,9 +266,7 @@ def validate_instruction(path) raise "Invalid instruction definition: #{obj}" unless obj.is_a?(Hash) inst_name = path.basename('.yaml').to_s - raise "Invalid instruction definition: #{inst_name} #{obj}" unless obj.key?(inst_name) - - obj = obj[inst_name] + raise "Invalid instruction definition: #{inst_name} #{obj}" unless obj["name"] == inst_name if (obj["encoding"]["RV32"].nil?) validate_instruction_encoding(inst_name, obj["encoding"]) diff --git a/lib/yaml_loader.rb b/lib/yaml_loader.rb index ac3e67a0c..c545d369e 100644 --- a/lib/yaml_loader.rb +++ b/lib/yaml_loader.rb @@ -17,8 +17,48 @@ def self.expand(filename, obj, yaml_opts = {}) new_obj = if obj.keys.include?("$ref") # according JSON Reference, all keys except $ref are ignored - ref_target = obj["$ref"] - self.get_ref_target_obj(filename, ref_target, yaml_opts) + relative_path = obj["$ref"].split("#")[0] + if relative_path.empty? + # this is a reference in the same document + obj_doc = YAML.load_file(filename, **yaml_opts) + obj_path = obj["$ref"].split("#")[1].split("/")[1..] + target_obj = obj_doc.dig(*obj_path) + raise DereferenceError, "#{obj['$ref']} cannot be found" if target_obj.nil? + + ref = expand(filename, target_obj, yaml_opts) + if ref.nil? + raise DereferenceError, "JSON Path #{obj['$ref'].split('#')[1]} does not exist in #{filename}" + end + + { "$ref" => obj["$ref"] } # ignore any other keys that might exist + else + target_filename = + if File.exist?(File.join(filename.dirname, relative_path)) + File.realpath(File.join(filename.dirname, relative_path)) + elsif File.exist?(File.join($root, 'arch', relative_path)) + File.join($root, 'arch', relative_path) + else + raise DereferenceError, "#{relative_path} cannot be found" + end + + obj_doc = YamlLoader.load(target_filename, yaml_opts) + file_path, obj_path = obj["$ref"].split("#") + target_obj = + if obj_path.nil? + obj_doc + else + obj_doc.dig(*(obj_path.split("/")[1..])) + + end + raise "#{obj['$ref']} cannot be found" if target_obj.nil? + + ref = expand(target_filename, target_obj, yaml_opts) + if ref.nil? + raise DereferenceError, "JSON Path #{obj['$ref'].split('#')[1]} does not exist in #{target_filename}" + end + + { "$ref" => obj["$ref"] } # ignore any other keys that might exist + end elsif obj.keys.include?("$inherits") # we handle the inherits key first so that any override will take priority inherits = obj["$inherits"] @@ -30,8 +70,24 @@ def self.expand(filename, obj, yaml_opts = {}) new_obj = {} inherits_targets.each do |inherits_target| - target_obj = get_inherits_target_obj(filename, inherits_target, yaml_opts) - + relative_path = inherits_target.split("#")[0] + target_obj = + if relative_path.empty? + YAML.load_file(filename, **yaml_opts) + else + target_filename = + if File.exist?(File.join(filename.dirname, relative_path)) + File.realpath(File.join(filename.dirname, relative_path)) + elsif File.exist?(File.join($root, 'arch', relative_path)) + File.join($root, 'arch', relative_path) + else + raise DereferenceError, "#{relative_path} cannot be found" + end + + unless File.exist?(target_filename) + raise DereferenceError, "While locating $inherits in #{filename}, #{target_filename} does not exist" + end + raise ArgumentError, "$inherits: \"#{inherits_target}\" in file #{filename} references a #{target_obj.class} but needs to reference a Hash" unless target_obj.is_a?(Hash) target_obj = expand(filename, target_obj, yaml_opts) @@ -128,41 +184,6 @@ def self.get_ref_target_obj(filename, ref_target, yaml_opts) end end - # @param filename [String,Pathname] path to the YAML file - # @param inherits_target [String] - # @param yaml_opts [Hash] options to pass to YAML.load_file - # @return [Object] - def self.get_inherits_target_obj(filename, inherits_target, yaml_opts) - relative_path = inherits_target.split("#")[0] - target_obj = - if relative_path.empty? - YAML.load_file(filename, **yaml_opts) - else - target_filename = File.realpath(File.join(filename.dirname, relative_path)) - - unless File.exist?(target_filename) - raise DereferenceError, "While locating $inherits in #{filename}, #{target_filename} does not exist" - end - - YamlLoader.load(target_filename, yaml_opts) - end - - inherits_target_suffix = inherits_target.split("#/")[1] - inherits_target_path = inherits_target_suffix.split("/") - begin - target_obj = target_obj.dig(*inherits_target_path) - rescue TypeError => e - if e.message == "no implicit conversion of String into Integer" - warn "$inherits: \"#{inherits_target}\" found in file #{filename} references an Array but needs to reference a Hash" - end - raise e - end - - raise DereferenceError, "JSON Path #{inherits_target_suffix} in file #{filename} does not exist in #{relative_path}" if target_obj.nil? - - target_obj - end - # load a YAML file and expand any $ref/$inherits references # @param filename [String,Pathname] path to the YAML file # @param yaml_opts [Hash] options to pass to YAML.load_file diff --git a/schemas/arch_schema.json b/schemas/arch_schema.json index 8753fea0e..385784650 100644 --- a/schemas/arch_schema.json +++ b/schemas/arch_schema.json @@ -70,19 +70,15 @@ } }, "extensions": { - "type": "object", - "patternProperties": { - ".*": { - "$ref": "ext_schema.json#/$defs/ext_data" - } + "type": "array", + "items": { + "$ref": "ext_schema.json#/$defs/ext_data" } }, "csrs": { - "type": "object", - "patternProperties": { - ".*": { - "$ref": "csr_schema.json#/$defs/csr_register" - } + "type": "array", + "items": { + "$ref": "csr_schema.json#/$defs/csr_register" } }, "implemented_csrs": { @@ -95,12 +91,9 @@ } }, "instructions": { - "type": "object", - "patternProperties": { - ".*": { - "$ref": "inst_schema.json#/$defs/inst_data" - }, - "additionalProperties": false + "type": "array", + "items": { + "$ref": "inst_schema.json#" } }, "implemented_instructions": { @@ -125,10 +118,16 @@ "type": "object" }, "certificate_classes": { - "type": "object" + "type": "array", + "items": { + "$ref": "cert_class_schema.json#" + } }, "certificate_models": { - "type": "object" + "type": "array", + "items": { + "$ref": "cert_model_schema.json#" + } } }, "additionalProperties": false diff --git a/schemas/cert_class_schema.json b/schemas/cert_class_schema.json new file mode 100644 index 000000000..d7f7ff80c --- /dev/null +++ b/schemas/cert_class_schema.json @@ -0,0 +1,47 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + + "type": "object", + "required": ["$schema", "kind", "name", "long_name", "introduction"], + "additionalProperties": false, + "properties": { + "$schema": { + "type": "string", + "const": "cert_class_schema.json#" + }, + "kind": { + "type": "string", + "const": "certificate class" + }, + "name": { + "type": "string", + "pattern": "^[A-Z][a-zA-Z0-9_]*$", + "description": "The short name of the class, used as a database key" + }, + "long_name": { + "type": "string", + "description": "Descriptive name of the class" + }, + "introduction": { + "type": "string", + "description": "Asciidoc text containing the introduction prose for the class" + }, + "naming_scheme": { + "type": "string", + "description": "Asciidoc text describing the naming scheme for the class" + }, + "mandatory_priv_modes": { + "type": "array", + "items": { + "type": "string", + "enum": ["M", "S", "U", "VS", "VU"] + }, + "uniqueItems": true, + "minItems": 1, + "description": "List of mandatory privilege modes for the class" + }, + "__source": { + "$ref": "schema_defs.json#/$defs/__source" + } + } +} \ No newline at end of file diff --git a/schemas/cert_model_schema.json b/schemas/cert_model_schema.json new file mode 100644 index 000000000..b20551445 --- /dev/null +++ b/schemas/cert_model_schema.json @@ -0,0 +1,199 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + + "type": "object", + "required": ["$schema", "kind", "name", "long_name"], + "additionalProperties": false, + "properties": { + "$schema": { + "type": "string", + "const": "cert_model_schema.json#" + }, + "kind": { + "type": "string", + "const": "certificate model" + }, + "name": { + "type": "string", + "pattern": "^[A-Z][a-zA-Z0-9_]*$", + "description": "The short name of the model, used as a database key" + }, + "long_name": { + "type": "string", + "description": "Descriptive name of the class" + }, + "class": { + "type": "object", + "properties": { + "$ref": { + "type": "string", + "pattern": "^certificate_class/[A-Z][a-zA-Z0-9_]*\\.yaml#" + } + }, + "description": "Reference to the class this model belongs to" + }, + "versions": { + "type": "array", + "items": { + "type": "object", + "required": ["version"], + "properties": { + "version": { + "$ref": "schema_defs.json#/$defs/semantic_version" + } + }, + "additionalProperties": false + }, + "minItems": 1, + "description": "List of semantic versions within the model" + }, + "base": { + "type": "integer", + "enum": [32, 64], + "description": "Base of the model" + }, + "revision_history": { + "type": "array", + "items": { + "$ref": "schema_defs.json#/$defs/revision_history_entry" + }, + "minItems": 1, + "description": "Revisions of the model document" + }, + "description": { + "type": "string", + "description": "Asciidoc description" + }, + "tsc_profile": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "object", + "required": ["$ref"], + "properties": { + "$ref": { + "type": "string", + "pattern": "^profile_release/[A-Z][a-zA-Z0-9_]*\\.yaml#" + } + }, + "additionalProperties": false + } + ], + "description": "Profile certified by this model" + }, + "unpriv_isa_manual_revision": { + "type": "string" + }, + "priv_isa_manual_revision": { + "type": "string" + }, + "debug_manual_revision": { + "type": "string" + }, + "extensions": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^\\$inherits": { + "oneOf": [ + { + "type": "string", + "pattern": "^profile_release/.*\\.yaml#.*" + }, + { + "type": "array", + "items": { + "type": "string", + "pattern": "^profile_release/.*\\.yaml#.*" + }, + "uniqueItems": true + } + ] + }, + "^([A-WY])|([SXZ][a-z0-9]+)$": { + "type": "object", + "properties": { + "version": { + "$ref": "schema_defs.json#/$defs/requirement_string" + }, + "presence": { + "$ref": "schema_defs.json#/$defs/extension_presence" + }, + "parameters": { + "type": "object", + "patternProperties": { + "^[A-Z][A-Z0-9_]+$": { + "$ref": "schema_defs.json#/$defs/parameter_constraint" + } + } + }, + "note": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "requirement_groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "requirements": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "when": { + "$ref": "schema_defs.json#/$defs/when_condition" + } + }, + "additionalProperties": false + } + } + } + } + }, + "extra_notes": { + "type": "array", + "items": { + "type": "object", + "properties": { + "presence": { + "$ref": "schema_defs.json#/$defs/extension_presence" + }, + "text": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "recommendations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "text": { + "type": "string" + } + } + } + }, + "__source": { + "$ref": "schema_defs.json#/$defs/__source" + } + } +} \ No newline at end of file diff --git a/schemas/csr_schema.json b/schemas/csr_schema.json index 564577834..ae0e26d18 100644 --- a/schemas/csr_schema.json +++ b/schemas/csr_schema.json @@ -164,12 +164,24 @@ }, "csr_register": { "type": "object", - "required": ["long_name", "length", "description", "priv_mode", "definedBy"], + "required": ["$schema", "kind", "name", "long_name", "length", "description", "priv_mode", "definedBy"], "properties": { + "$schema": { + "type": "string", + "format": "uri-reference", + "const": "csr_schema.json#", + "description": "Path to schema, relative to /schemas" + }, + "kind": { + "type": "string", + "const": "csr", + "description": "Object type" + }, "name": { "type": "string", - "description": "Optional name (name is extracted from object key of parent), so information is redundant" + "pattern": "^[a-z][a-z0-9]+$", + "description": "CSR name" }, "base": { "type": "integer", @@ -274,19 +286,5 @@ } }, - "type": "object", - "examples": [ - "misa:\\n long_name: Machine ISA Control\\n address: 0x301\\n priv_mode: M\\n length: 64\\n description: Reports the XLEN and 'major' extensions supported by the ISA.\\n definedBy: I\\n fields:\\n MXL:\\n location: 63-62\\n description: XLEN in M-mode.\\n type: RO\\n value: 2\\n Extensions: location: 25-0\\n description: |\\n Indicates support for major (single letter) ISA extensions.\\n\\n Value corresponds to A, D, F, H, I, M, S, U\\n type: RO\\n value: 0x1411A9" - ], - "patternProperties": { - "^[a-z][a-z0-9A-Z_]+$": { - "description": "CSR name", - "$ref": "#/$defs/csr_register" - } - }, - - "$comment": "We are using a key as the CSR name, so there should only be one property", - "maxProperties": 1, - - "additionalProperties": false + "$ref": "#/$defs/csr_register" } diff --git a/schemas/ext_schema.json b/schemas/ext_schema.json index 30d63cfc5..8c281c4e6 100644 --- a/schemas/ext_schema.json +++ b/schemas/ext_schema.json @@ -39,8 +39,19 @@ }, "ext_data": { "type": "object", - "required": ["description", "long_name", "versions"], + "required": ["$schema", "kind", "name", "description", "long_name", "versions"], "properties": { + "$schema": { + "type": "string", + "format": "uri-reference", + "const": "ext_schema.json#", + "description": "Path to schema, relative to /schemas" + }, + "kind": { + "type": "string", + "const": "extension", + "description": "Object type" + }, "name": { "$ref": "schema_defs.json#/$defs/extension_name" }, "long_name": { "type": "string", @@ -276,12 +287,5 @@ } }, - "type": "object", - "patternProperties": { - "^([A-WY])|([SXZ][a-z0-9]+)$": { - "$ref": "#/$defs/ext_data" - } - }, - "additionalProperties": false, - "maxProperties": 1 + "$ref": "#/$defs/ext_data" } \ No newline at end of file diff --git a/schemas/inst_schema.json b/schemas/inst_schema.json index 547967779..ac1c0082d 100644 --- a/schemas/inst_schema.json +++ b/schemas/inst_schema.json @@ -64,7 +64,7 @@ }, "$inherits": { "type": "string", - "pattern": "^(\\.\\./)+common/inst_variable_types\\.yaml#/[a-zA-Z0-9_]+", + "pattern": "^common/inst_variable_types\\.yaml#/[a-zA-Z0-9_]+", "description": "Reference to variable metadata" } }, @@ -146,9 +146,19 @@ }, "inst_data": { "type": "object", - "required": ["long_name", "description", "definedBy", "access", "assembly"], + "required": ["$schema", "kind", "name", "long_name", "description", "definedBy", "access", "assembly"], "additionalProperties": false, "properties": { + "$schema": { + "type": "string", + "format": "uri-reference", + "const": "inst_schema.json#", + "description": "Path to schema, relative to /schemas" + }, + "kind": { + "type": "string", + "const": "instruction" + }, "name": { "type": "string", "pattern": "^[a-z0-9.]+$", @@ -268,13 +278,5 @@ } }, - "type": "object", - "title": "Instruction specification", - "patternProperties": { - ".*": { - "$ref": "#/$defs/inst_data" - } - }, - "additionalProperties": false, - "maxProperties": 1 + "$ref": "#/$defs/inst_data" } diff --git a/schemas/schema_defs.json b/schemas/schema_defs.json index 82d35dd7a..92458826d 100644 --- a/schemas/schema_defs.json +++ b/schemas/schema_defs.json @@ -4,6 +4,11 @@ "title": "Common patterns used by all schemas", "$defs": { + "__source": { + "type": "string", + "format": "uri-reference", + "description": "Path to the source file containing this object" + }, "semantic_version": { "type": "string", "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" @@ -15,6 +20,29 @@ ], "description": "Location of a field in a register" }, + "revision_history_entry": { + "type": "object", + "properties": { + "revision": { + "$ref": "#/$defs/semantic_version", + "description": "Revision number" + }, + "date": { + "type": "string", + "format": "date", + "description": "The date of the change" + }, + "changes": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of changes" + } + }, + "required": ["date", "revision", "changes"], + "additionalProperties": false + }, "spec_state": { "type": "string", "enum": [ @@ -26,6 +54,29 @@ "nonstandard-released" ] }, + "extension_presence": { + "oneOf": [ + { + "type": "string", + "enum": [ + "mandatory", + "optional", + "prohibited" + ] + }, + { + "type": "object", + "required": ["optional"], + "properties": { + "optional": { + "type": "string", + "enum": ["localized", "development", "expansion", "transitory"] + } + }, + "additionalProperties": false + } + ] + }, "date": { "type": "string", "format": "date", @@ -161,6 +212,17 @@ } }, "additionalProperties": false + }, + "parameter_constraint": { + "type": "object", + "properties": { + "schema": { + "$ref": "json-schema-draft-07.json#" + }, + "when": { + "$ref": "#/$defs/when_condition" + } + } } } } \ No newline at end of file